1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33#include <linux/types.h>
34#include <linux/vmalloc.h>
35#include <asm/xen/hypervisor.h>
36#include <xen/interface/xen.h>
37#include <xen/interface/event_channel.h>
38#include <xen/events.h>
39#include <xen/grant_table.h>
40#include <xen/xenbus.h>
41
42const char *xenbus_strstate(enum xenbus_state state)
43{
44 static const char *const name[] = {
45 [ XenbusStateUnknown ] = "Unknown",
46 [ XenbusStateInitialising ] = "Initialising",
47 [ XenbusStateInitWait ] = "InitWait",
48 [ XenbusStateInitialised ] = "Initialised",
49 [ XenbusStateConnected ] = "Connected",
50 [ XenbusStateClosing ] = "Closing",
51 [ XenbusStateClosed ] = "Closed",
52 };
53 return (state < ARRAY_SIZE(name)) ? name[state] : "INVALID";
54}
55EXPORT_SYMBOL_GPL(xenbus_strstate);
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71int xenbus_watch_path(struct xenbus_device *dev, const char *path,
72 struct xenbus_watch *watch,
73 void (*callback)(struct xenbus_watch *,
74 const char **, unsigned int))
75{
76 int err;
77
78 watch->node = path;
79 watch->callback = callback;
80
81 err = register_xenbus_watch(watch);
82
83 if (err) {
84 watch->node = NULL;
85 watch->callback = NULL;
86 xenbus_dev_fatal(dev, err, "adding watch on %s", path);
87 }
88
89 return err;
90}
91EXPORT_SYMBOL_GPL(xenbus_watch_path);
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109int xenbus_watch_pathfmt(struct xenbus_device *dev,
110 struct xenbus_watch *watch,
111 void (*callback)(struct xenbus_watch *,
112 const char **, unsigned int),
113 const char *pathfmt, ...)
114{
115 int err;
116 va_list ap;
117 char *path;
118
119 va_start(ap, pathfmt);
120 path = kvasprintf(GFP_NOIO | __GFP_HIGH, pathfmt, ap);
121 va_end(ap);
122
123 if (!path) {
124 xenbus_dev_fatal(dev, -ENOMEM, "allocating path for watch");
125 return -ENOMEM;
126 }
127 err = xenbus_watch_path(dev, path, watch, callback);
128
129 if (err)
130 kfree(path);
131 return err;
132}
133EXPORT_SYMBOL_GPL(xenbus_watch_pathfmt);
134
135
136
137
138
139
140
141
142
143
144
145
146int xenbus_switch_state(struct xenbus_device *dev, enum xenbus_state state)
147{
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162 int current_state;
163 int err;
164
165 if (state == dev->state)
166 return 0;
167
168 err = xenbus_scanf(XBT_NIL, dev->nodename, "state", "%d",
169 ¤t_state);
170 if (err != 1)
171 return 0;
172
173 err = xenbus_printf(XBT_NIL, dev->nodename, "state", "%d", state);
174 if (err) {
175 if (state != XenbusStateClosing)
176 xenbus_dev_fatal(dev, err, "writing new state");
177 return err;
178 }
179
180 dev->state = state;
181
182 return 0;
183}
184EXPORT_SYMBOL_GPL(xenbus_switch_state);
185
186int xenbus_frontend_closed(struct xenbus_device *dev)
187{
188 xenbus_switch_state(dev, XenbusStateClosed);
189 complete(&dev->down);
190 return 0;
191}
192EXPORT_SYMBOL_GPL(xenbus_frontend_closed);
193
194
195
196
197
198static char *error_path(struct xenbus_device *dev)
199{
200 return kasprintf(GFP_KERNEL, "error/%s", dev->nodename);
201}
202
203
204static void xenbus_va_dev_error(struct xenbus_device *dev, int err,
205 const char *fmt, va_list ap)
206{
207 int ret;
208 unsigned int len;
209 char *printf_buffer = NULL;
210 char *path_buffer = NULL;
211
212#define PRINTF_BUFFER_SIZE 4096
213 printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_KERNEL);
214 if (printf_buffer == NULL)
215 goto fail;
216
217 len = sprintf(printf_buffer, "%i ", -err);
218 ret = vsnprintf(printf_buffer+len, PRINTF_BUFFER_SIZE-len, fmt, ap);
219
220 BUG_ON(len + ret > PRINTF_BUFFER_SIZE-1);
221
222 dev_err(&dev->dev, "%s\n", printf_buffer);
223
224 path_buffer = error_path(dev);
225
226 if (path_buffer == NULL) {
227 dev_err(&dev->dev, "failed to write error node for %s (%s)\n",
228 dev->nodename, printf_buffer);
229 goto fail;
230 }
231
232 if (xenbus_write(XBT_NIL, path_buffer, "error", printf_buffer) != 0) {
233 dev_err(&dev->dev, "failed to write error node for %s (%s)\n",
234 dev->nodename, printf_buffer);
235 goto fail;
236 }
237
238fail:
239 kfree(printf_buffer);
240 kfree(path_buffer);
241}
242
243
244
245
246
247
248
249
250
251
252
253void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt, ...)
254{
255 va_list ap;
256
257 va_start(ap, fmt);
258 xenbus_va_dev_error(dev, err, fmt, ap);
259 va_end(ap);
260}
261EXPORT_SYMBOL_GPL(xenbus_dev_error);
262
263
264
265
266
267
268
269
270
271
272
273
274void xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt, ...)
275{
276 va_list ap;
277
278 va_start(ap, fmt);
279 xenbus_va_dev_error(dev, err, fmt, ap);
280 va_end(ap);
281
282 xenbus_switch_state(dev, XenbusStateClosing);
283}
284EXPORT_SYMBOL_GPL(xenbus_dev_fatal);
285
286
287
288
289
290
291
292
293
294
295int xenbus_grant_ring(struct xenbus_device *dev, unsigned long ring_mfn)
296{
297 int err = gnttab_grant_foreign_access(dev->otherend_id, ring_mfn, 0);
298 if (err < 0)
299 xenbus_dev_fatal(dev, err, "granting access to ring page");
300 return err;
301}
302EXPORT_SYMBOL_GPL(xenbus_grant_ring);
303
304
305
306
307
308
309
310
311int xenbus_alloc_evtchn(struct xenbus_device *dev, int *port)
312{
313 struct evtchn_alloc_unbound alloc_unbound;
314 int err;
315
316 alloc_unbound.dom = DOMID_SELF;
317 alloc_unbound.remote_dom = dev->otherend_id;
318
319 err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound,
320 &alloc_unbound);
321 if (err)
322 xenbus_dev_fatal(dev, err, "allocating event channel");
323 else
324 *port = alloc_unbound.port;
325
326 return err;
327}
328EXPORT_SYMBOL_GPL(xenbus_alloc_evtchn);
329
330
331
332
333
334
335
336int xenbus_bind_evtchn(struct xenbus_device *dev, int remote_port, int *port)
337{
338 struct evtchn_bind_interdomain bind_interdomain;
339 int err;
340
341 bind_interdomain.remote_dom = dev->otherend_id;
342 bind_interdomain.remote_port = remote_port;
343
344 err = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain,
345 &bind_interdomain);
346 if (err)
347 xenbus_dev_fatal(dev, err,
348 "binding to event channel %d from domain %d",
349 remote_port, dev->otherend_id);
350 else
351 *port = bind_interdomain.local_port;
352
353 return err;
354}
355EXPORT_SYMBOL_GPL(xenbus_bind_evtchn);
356
357
358
359
360
361int xenbus_free_evtchn(struct xenbus_device *dev, int port)
362{
363 struct evtchn_close close;
364 int err;
365
366 close.port = port;
367
368 err = HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
369 if (err)
370 xenbus_dev_error(dev, err, "freeing event channel %d", port);
371
372 return err;
373}
374EXPORT_SYMBOL_GPL(xenbus_free_evtchn);
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391int xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref, void **vaddr)
392{
393 struct gnttab_map_grant_ref op = {
394 .flags = GNTMAP_host_map,
395 .ref = gnt_ref,
396 .dom = dev->otherend_id,
397 };
398 struct vm_struct *area;
399
400 *vaddr = NULL;
401
402 area = xen_alloc_vm_area(PAGE_SIZE);
403 if (!area)
404 return -ENOMEM;
405
406 op.host_addr = (unsigned long)area->addr;
407
408 if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
409 BUG();
410
411 if (op.status != GNTST_okay) {
412 xen_free_vm_area(area);
413 xenbus_dev_fatal(dev, op.status,
414 "mapping in shared page %d from domain %d",
415 gnt_ref, dev->otherend_id);
416 return op.status;
417 }
418
419
420 area->phys_addr = (unsigned long)op.handle;
421
422 *vaddr = area->addr;
423 return 0;
424}
425EXPORT_SYMBOL_GPL(xenbus_map_ring_valloc);
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442int xenbus_map_ring(struct xenbus_device *dev, int gnt_ref,
443 grant_handle_t *handle, void *vaddr)
444{
445 struct gnttab_map_grant_ref op = {
446 .host_addr = (unsigned long)vaddr,
447 .flags = GNTMAP_host_map,
448 .ref = gnt_ref,
449 .dom = dev->otherend_id,
450 };
451
452 if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
453 BUG();
454
455 if (op.status != GNTST_okay) {
456 xenbus_dev_fatal(dev, op.status,
457 "mapping in shared page %d from domain %d",
458 gnt_ref, dev->otherend_id);
459 } else
460 *handle = op.handle;
461
462 return op.status;
463}
464EXPORT_SYMBOL_GPL(xenbus_map_ring);
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr)
480{
481 struct vm_struct *area;
482 struct gnttab_unmap_grant_ref op = {
483 .host_addr = (unsigned long)vaddr,
484 };
485
486
487
488
489
490
491
492 read_lock(&vmlist_lock);
493 for (area = vmlist; area != NULL; area = area->next) {
494 if (area->addr == vaddr)
495 break;
496 }
497 read_unlock(&vmlist_lock);
498
499 if (!area) {
500 xenbus_dev_error(dev, -ENOENT,
501 "can't find mapped virtual address %p", vaddr);
502 return GNTST_bad_virt_addr;
503 }
504
505 op.handle = (grant_handle_t)area->phys_addr;
506
507 if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
508 BUG();
509
510 if (op.status == GNTST_okay)
511 xen_free_vm_area(area);
512 else
513 xenbus_dev_error(dev, op.status,
514 "unmapping page at handle %d error %d",
515 (int16_t)area->phys_addr, op.status);
516
517 return op.status;
518}
519EXPORT_SYMBOL_GPL(xenbus_unmap_ring_vfree);
520
521
522
523
524
525
526
527
528
529
530
531
532int xenbus_unmap_ring(struct xenbus_device *dev,
533 grant_handle_t handle, void *vaddr)
534{
535 struct gnttab_unmap_grant_ref op = {
536 .host_addr = (unsigned long)vaddr,
537 .handle = handle,
538 };
539
540 if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
541 BUG();
542
543 if (op.status != GNTST_okay)
544 xenbus_dev_error(dev, op.status,
545 "unmapping page at handle %d error %d",
546 handle, op.status);
547
548 return op.status;
549}
550EXPORT_SYMBOL_GPL(xenbus_unmap_ring);
551
552
553
554
555
556
557
558
559
560enum xenbus_state xenbus_read_driver_state(const char *path)
561{
562 enum xenbus_state result;
563 int err = xenbus_gather(XBT_NIL, path, "state", "%d", &result, NULL);
564 if (err)
565 result = XenbusStateUnknown;
566
567 return result;
568}
569EXPORT_SYMBOL_GPL(xenbus_read_driver_state);
570