]>
Commit | Line | Data |
---|---|---|
4bac07c9 JF |
1 | /****************************************************************************** |
2 | * Client-facing interface for the Xenbus driver. In other words, the | |
3 | * interface between the Xenbus and the device-specific code, be it the | |
4 | * frontend or the backend of that driver. | |
5 | * | |
6 | * Copyright (C) 2005 XenSource Ltd | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU General Public License version 2 | |
10 | * as published by the Free Software Foundation; or, when distributed | |
11 | * separately from the Linux kernel or incorporated into other | |
12 | * software packages, subject to the following license: | |
13 | * | |
14 | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
15 | * of this source file (the "Software"), to deal in the Software without | |
16 | * restriction, including without limitation the rights to use, copy, modify, | |
17 | * merge, publish, distribute, sublicense, and/or sell copies of the Software, | |
18 | * and to permit persons to whom the Software is furnished to do so, subject to | |
19 | * the following conditions: | |
20 | * | |
21 | * The above copyright notice and this permission notice shall be included in | |
22 | * all copies or substantial portions of the Software. | |
23 | * | |
24 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
25 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
26 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
27 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
28 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
29 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | |
30 | * IN THE SOFTWARE. | |
31 | */ | |
32 | ||
45e27161 | 33 | #include <linux/mm.h> |
5a0e3ad6 | 34 | #include <linux/slab.h> |
4bac07c9 | 35 | #include <linux/types.h> |
2c5d37d3 | 36 | #include <linux/spinlock.h> |
4bac07c9 | 37 | #include <linux/vmalloc.h> |
63c9744b | 38 | #include <linux/export.h> |
4bac07c9 | 39 | #include <asm/xen/hypervisor.h> |
a9fd60e2 | 40 | #include <xen/page.h> |
4bac07c9 JF |
41 | #include <xen/interface/xen.h> |
42 | #include <xen/interface/event_channel.h> | |
2c5d37d3 | 43 | #include <xen/balloon.h> |
4bac07c9 JF |
44 | #include <xen/events.h> |
45 | #include <xen/grant_table.h> | |
46 | #include <xen/xenbus.h> | |
2c5d37d3 | 47 | #include <xen/xen.h> |
be3e9cf3 | 48 | #include <xen/features.h> |
2c5d37d3 | 49 | |
332f791d | 50 | #include "xenbus.h" |
2c5d37d3 | 51 | |
89bf4b4e JG |
52 | #define XENBUS_PAGES(_grants) (DIV_ROUND_UP(_grants, XEN_PFN_PER_PAGE)) |
53 | ||
54 | #define XENBUS_MAX_RING_PAGES (XENBUS_PAGES(XENBUS_MAX_RING_GRANTS)) | |
55 | ||
2c5d37d3 DDG |
56 | struct xenbus_map_node { |
57 | struct list_head next; | |
58 | union { | |
ccc9d90a WL |
59 | struct { |
60 | struct vm_struct *area; | |
61 | } pv; | |
62 | struct { | |
89bf4b4e JG |
63 | struct page *pages[XENBUS_MAX_RING_PAGES]; |
64 | unsigned long addrs[XENBUS_MAX_RING_GRANTS]; | |
ccc9d90a WL |
65 | void *addr; |
66 | } hvm; | |
2c5d37d3 | 67 | }; |
9cce2914 | 68 | grant_handle_t handles[XENBUS_MAX_RING_GRANTS]; |
ccc9d90a | 69 | unsigned int nr_handles; |
2c5d37d3 DDG |
70 | }; |
71 | ||
72 | static DEFINE_SPINLOCK(xenbus_valloc_lock); | |
73 | static LIST_HEAD(xenbus_valloc_pages); | |
74 | ||
75 | struct xenbus_ring_ops { | |
ccc9d90a WL |
76 | int (*map)(struct xenbus_device *dev, |
77 | grant_ref_t *gnt_refs, unsigned int nr_grefs, | |
78 | void **vaddr); | |
2c5d37d3 DDG |
79 | int (*unmap)(struct xenbus_device *dev, void *vaddr); |
80 | }; | |
81 | ||
82 | static const struct xenbus_ring_ops *ring_ops __read_mostly; | |
4bac07c9 JF |
83 | |
84 | const char *xenbus_strstate(enum xenbus_state state) | |
85 | { | |
86 | static const char *const name[] = { | |
87 | [ XenbusStateUnknown ] = "Unknown", | |
88 | [ XenbusStateInitialising ] = "Initialising", | |
89 | [ XenbusStateInitWait ] = "InitWait", | |
90 | [ XenbusStateInitialised ] = "Initialised", | |
91 | [ XenbusStateConnected ] = "Connected", | |
92 | [ XenbusStateClosing ] = "Closing", | |
93 | [ XenbusStateClosed ] = "Closed", | |
89afb6e4 YI |
94 | [XenbusStateReconfiguring] = "Reconfiguring", |
95 | [XenbusStateReconfigured] = "Reconfigured", | |
4bac07c9 JF |
96 | }; |
97 | return (state < ARRAY_SIZE(name)) ? name[state] : "INVALID"; | |
98 | } | |
99 | EXPORT_SYMBOL_GPL(xenbus_strstate); | |
100 | ||
101 | /** | |
102 | * xenbus_watch_path - register a watch | |
103 | * @dev: xenbus device | |
104 | * @path: path to watch | |
105 | * @watch: watch to register | |
106 | * @callback: callback to register | |
107 | * | |
108 | * Register a @watch on the given path, using the given xenbus_watch structure | |
109 | * for storage, and the given @callback function as the callback. Return 0 on | |
110 | * success, or -errno on error. On success, the given @path will be saved as | |
111 | * @watch->node, and remains the caller's to free. On error, @watch->node will | |
112 | * be NULL, the device will switch to %XenbusStateClosing, and the error will | |
113 | * be saved in the store. | |
114 | */ | |
115 | int xenbus_watch_path(struct xenbus_device *dev, const char *path, | |
116 | struct xenbus_watch *watch, | |
117 | void (*callback)(struct xenbus_watch *, | |
5584ea25 | 118 | const char *, const char *)) |
4bac07c9 JF |
119 | { |
120 | int err; | |
121 | ||
122 | watch->node = path; | |
123 | watch->callback = callback; | |
124 | ||
125 | err = register_xenbus_watch(watch); | |
126 | ||
127 | if (err) { | |
128 | watch->node = NULL; | |
129 | watch->callback = NULL; | |
130 | xenbus_dev_fatal(dev, err, "adding watch on %s", path); | |
131 | } | |
132 | ||
133 | return err; | |
134 | } | |
135 | EXPORT_SYMBOL_GPL(xenbus_watch_path); | |
136 | ||
137 | ||
138 | /** | |
139 | * xenbus_watch_pathfmt - register a watch on a sprintf-formatted path | |
140 | * @dev: xenbus device | |
141 | * @watch: watch to register | |
142 | * @callback: callback to register | |
143 | * @pathfmt: format of path to watch | |
144 | * | |
145 | * Register a watch on the given @path, using the given xenbus_watch | |
146 | * structure for storage, and the given @callback function as the callback. | |
147 | * Return 0 on success, or -errno on error. On success, the watched path | |
148 | * (@path/@path2) will be saved as @watch->node, and becomes the caller's to | |
149 | * kfree(). On error, watch->node will be NULL, so the caller has nothing to | |
150 | * free, the device will switch to %XenbusStateClosing, and the error will be | |
151 | * saved in the store. | |
152 | */ | |
153 | int xenbus_watch_pathfmt(struct xenbus_device *dev, | |
154 | struct xenbus_watch *watch, | |
155 | void (*callback)(struct xenbus_watch *, | |
5584ea25 | 156 | const char *, const char *), |
4bac07c9 JF |
157 | const char *pathfmt, ...) |
158 | { | |
159 | int err; | |
160 | va_list ap; | |
161 | char *path; | |
162 | ||
163 | va_start(ap, pathfmt); | |
a144ff09 | 164 | path = kvasprintf(GFP_NOIO | __GFP_HIGH, pathfmt, ap); |
4bac07c9 JF |
165 | va_end(ap); |
166 | ||
167 | if (!path) { | |
168 | xenbus_dev_fatal(dev, -ENOMEM, "allocating path for watch"); | |
169 | return -ENOMEM; | |
170 | } | |
171 | err = xenbus_watch_path(dev, path, watch, callback); | |
172 | ||
173 | if (err) | |
174 | kfree(path); | |
175 | return err; | |
176 | } | |
177 | EXPORT_SYMBOL_GPL(xenbus_watch_pathfmt); | |
178 | ||
5b61cb90 DS |
179 | static void xenbus_switch_fatal(struct xenbus_device *, int, int, |
180 | const char *, ...); | |
4bac07c9 | 181 | |
5b61cb90 DS |
182 | static int |
183 | __xenbus_switch_state(struct xenbus_device *dev, | |
184 | enum xenbus_state state, int depth) | |
4bac07c9 JF |
185 | { |
186 | /* We check whether the state is currently set to the given value, and | |
187 | if not, then the state is set. We don't want to unconditionally | |
188 | write the given state, because we don't want to fire watches | |
189 | unnecessarily. Furthermore, if the node has gone, we don't write | |
190 | to it, as the device will be tearing down, and we don't want to | |
191 | resurrect that directory. | |
192 | ||
5b61cb90 DS |
193 | Note that, because of this cached value of our state, this |
194 | function will not take a caller's Xenstore transaction | |
195 | (something it was trying to in the past) because dev->state | |
196 | would not get reset if the transaction was aborted. | |
4bac07c9 JF |
197 | */ |
198 | ||
5b61cb90 | 199 | struct xenbus_transaction xbt; |
4bac07c9 | 200 | int current_state; |
5b61cb90 | 201 | int err, abort; |
4bac07c9 JF |
202 | |
203 | if (state == dev->state) | |
204 | return 0; | |
205 | ||
5b61cb90 DS |
206 | again: |
207 | abort = 1; | |
208 | ||
209 | err = xenbus_transaction_start(&xbt); | |
210 | if (err) { | |
211 | xenbus_switch_fatal(dev, depth, err, "starting transaction"); | |
4bac07c9 | 212 | return 0; |
5b61cb90 | 213 | } |
4bac07c9 | 214 | |
5b61cb90 DS |
215 | err = xenbus_scanf(xbt, dev->nodename, "state", "%d", ¤t_state); |
216 | if (err != 1) | |
217 | goto abort; | |
218 | ||
219 | err = xenbus_printf(xbt, dev->nodename, "state", "%d", state); | |
4bac07c9 | 220 | if (err) { |
5b61cb90 DS |
221 | xenbus_switch_fatal(dev, depth, err, "writing new state"); |
222 | goto abort; | |
4bac07c9 JF |
223 | } |
224 | ||
5b61cb90 DS |
225 | abort = 0; |
226 | abort: | |
227 | err = xenbus_transaction_end(xbt, abort); | |
228 | if (err) { | |
229 | if (err == -EAGAIN && !abort) | |
230 | goto again; | |
231 | xenbus_switch_fatal(dev, depth, err, "ending transaction"); | |
232 | } else | |
233 | dev->state = state; | |
4bac07c9 JF |
234 | |
235 | return 0; | |
236 | } | |
5b61cb90 DS |
237 | |
238 | /** | |
239 | * xenbus_switch_state | |
240 | * @dev: xenbus device | |
241 | * @state: new state | |
242 | * | |
243 | * Advertise in the store a change of the given driver to the given new_state. | |
244 | * Return 0 on success, or -errno on error. On error, the device will switch | |
245 | * to XenbusStateClosing, and the error will be saved in the store. | |
246 | */ | |
247 | int xenbus_switch_state(struct xenbus_device *dev, enum xenbus_state state) | |
248 | { | |
249 | return __xenbus_switch_state(dev, state, 0); | |
250 | } | |
251 | ||
4bac07c9 JF |
252 | EXPORT_SYMBOL_GPL(xenbus_switch_state); |
253 | ||
254 | int xenbus_frontend_closed(struct xenbus_device *dev) | |
255 | { | |
256 | xenbus_switch_state(dev, XenbusStateClosed); | |
257 | complete(&dev->down); | |
258 | return 0; | |
259 | } | |
260 | EXPORT_SYMBOL_GPL(xenbus_frontend_closed); | |
261 | ||
4bac07c9 JF |
262 | static void xenbus_va_dev_error(struct xenbus_device *dev, int err, |
263 | const char *fmt, va_list ap) | |
264 | { | |
4bac07c9 | 265 | unsigned int len; |
c0d197d5 JP |
266 | char *printf_buffer; |
267 | char *path_buffer; | |
4bac07c9 JF |
268 | |
269 | #define PRINTF_BUFFER_SIZE 4096 | |
c0d197d5 | 270 | |
4bac07c9 | 271 | printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_KERNEL); |
c0d197d5 JP |
272 | if (!printf_buffer) |
273 | return; | |
4bac07c9 JF |
274 | |
275 | len = sprintf(printf_buffer, "%i ", -err); | |
c0d197d5 | 276 | vsnprintf(printf_buffer + len, PRINTF_BUFFER_SIZE - len, fmt, ap); |
4bac07c9 JF |
277 | |
278 | dev_err(&dev->dev, "%s\n", printf_buffer); | |
279 | ||
c0d197d5 JP |
280 | path_buffer = kasprintf(GFP_KERNEL, "error/%s", dev->nodename); |
281 | if (!path_buffer || | |
282 | xenbus_write(XBT_NIL, path_buffer, "error", printf_buffer)) | |
4bac07c9 | 283 | dev_err(&dev->dev, "failed to write error node for %s (%s)\n", |
c0d197d5 | 284 | dev->nodename, printf_buffer); |
4bac07c9 | 285 | |
4bac07c9 JF |
286 | kfree(printf_buffer); |
287 | kfree(path_buffer); | |
288 | } | |
289 | ||
4bac07c9 JF |
290 | /** |
291 | * xenbus_dev_error | |
292 | * @dev: xenbus device | |
293 | * @err: error to report | |
294 | * @fmt: error message format | |
295 | * | |
296 | * Report the given negative errno into the store, along with the given | |
297 | * formatted message. | |
298 | */ | |
299 | void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt, ...) | |
300 | { | |
301 | va_list ap; | |
302 | ||
303 | va_start(ap, fmt); | |
304 | xenbus_va_dev_error(dev, err, fmt, ap); | |
305 | va_end(ap); | |
306 | } | |
307 | EXPORT_SYMBOL_GPL(xenbus_dev_error); | |
308 | ||
309 | /** | |
310 | * xenbus_dev_fatal | |
311 | * @dev: xenbus device | |
312 | * @err: error to report | |
313 | * @fmt: error message format | |
314 | * | |
315 | * Equivalent to xenbus_dev_error(dev, err, fmt, args), followed by | |
d8220347 | 316 | * xenbus_switch_state(dev, XenbusStateClosing) to schedule an orderly |
4bac07c9 JF |
317 | * closedown of this driver and its peer. |
318 | */ | |
319 | ||
320 | void xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt, ...) | |
321 | { | |
322 | va_list ap; | |
323 | ||
324 | va_start(ap, fmt); | |
325 | xenbus_va_dev_error(dev, err, fmt, ap); | |
326 | va_end(ap); | |
327 | ||
328 | xenbus_switch_state(dev, XenbusStateClosing); | |
329 | } | |
330 | EXPORT_SYMBOL_GPL(xenbus_dev_fatal); | |
331 | ||
5b61cb90 DS |
332 | /** |
333 | * Equivalent to xenbus_dev_fatal(dev, err, fmt, args), but helps | |
334 | * avoiding recursion within xenbus_switch_state. | |
335 | */ | |
336 | static void xenbus_switch_fatal(struct xenbus_device *dev, int depth, int err, | |
337 | const char *fmt, ...) | |
338 | { | |
339 | va_list ap; | |
340 | ||
341 | va_start(ap, fmt); | |
342 | xenbus_va_dev_error(dev, err, fmt, ap); | |
343 | va_end(ap); | |
344 | ||
345 | if (!depth) | |
346 | __xenbus_switch_state(dev, XenbusStateClosing, 1); | |
347 | } | |
348 | ||
4bac07c9 JF |
349 | /** |
350 | * xenbus_grant_ring | |
351 | * @dev: xenbus device | |
ccc9d90a WL |
352 | * @vaddr: starting virtual address of the ring |
353 | * @nr_pages: number of pages to be granted | |
354 | * @grefs: grant reference array to be filled in | |
355 | * | |
356 | * Grant access to the given @vaddr to the peer of the given device. | |
357 | * Then fill in @grefs with grant references. Return 0 on success, or | |
358 | * -errno on error. On error, the device will switch to | |
359 | * XenbusStateClosing, and the error will be saved in the store. | |
4bac07c9 | 360 | */ |
ccc9d90a WL |
361 | int xenbus_grant_ring(struct xenbus_device *dev, void *vaddr, |
362 | unsigned int nr_pages, grant_ref_t *grefs) | |
4bac07c9 | 363 | { |
ccc9d90a WL |
364 | int err; |
365 | int i, j; | |
366 | ||
367 | for (i = 0; i < nr_pages; i++) { | |
ccc9d90a | 368 | err = gnttab_grant_foreign_access(dev->otherend_id, |
0df4f266 | 369 | virt_to_gfn(vaddr), 0); |
ccc9d90a WL |
370 | if (err < 0) { |
371 | xenbus_dev_fatal(dev, err, | |
372 | "granting access to ring page"); | |
373 | goto fail; | |
374 | } | |
375 | grefs[i] = err; | |
c9fd55eb | 376 | |
7d567928 | 377 | vaddr = vaddr + XEN_PAGE_SIZE; |
ccc9d90a WL |
378 | } |
379 | ||
380 | return 0; | |
381 | ||
382 | fail: | |
383 | for (j = 0; j < i; j++) | |
384 | gnttab_end_foreign_access_ref(grefs[j], 0); | |
4bac07c9 JF |
385 | return err; |
386 | } | |
387 | EXPORT_SYMBOL_GPL(xenbus_grant_ring); | |
388 | ||
389 | ||
390 | /** | |
391 | * Allocate an event channel for the given xenbus_device, assigning the newly | |
392 | * created local port to *port. Return 0 on success, or -errno on error. On | |
393 | * error, the device will switch to XenbusStateClosing, and the error will be | |
394 | * saved in the store. | |
395 | */ | |
396 | int xenbus_alloc_evtchn(struct xenbus_device *dev, int *port) | |
397 | { | |
398 | struct evtchn_alloc_unbound alloc_unbound; | |
399 | int err; | |
400 | ||
401 | alloc_unbound.dom = DOMID_SELF; | |
402 | alloc_unbound.remote_dom = dev->otherend_id; | |
403 | ||
404 | err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, | |
405 | &alloc_unbound); | |
406 | if (err) | |
407 | xenbus_dev_fatal(dev, err, "allocating event channel"); | |
408 | else | |
409 | *port = alloc_unbound.port; | |
410 | ||
411 | return err; | |
412 | } | |
413 | EXPORT_SYMBOL_GPL(xenbus_alloc_evtchn); | |
414 | ||
415 | ||
4bac07c9 JF |
416 | /** |
417 | * Free an existing event channel. Returns 0 on success or -errno on error. | |
418 | */ | |
419 | int xenbus_free_evtchn(struct xenbus_device *dev, int port) | |
420 | { | |
421 | struct evtchn_close close; | |
422 | int err; | |
423 | ||
424 | close.port = port; | |
425 | ||
426 | err = HYPERVISOR_event_channel_op(EVTCHNOP_close, &close); | |
427 | if (err) | |
428 | xenbus_dev_error(dev, err, "freeing event channel %d", port); | |
429 | ||
430 | return err; | |
431 | } | |
432 | EXPORT_SYMBOL_GPL(xenbus_free_evtchn); | |
433 | ||
434 | ||
435 | /** | |
436 | * xenbus_map_ring_valloc | |
437 | * @dev: xenbus device | |
ccc9d90a WL |
438 | * @gnt_refs: grant reference array |
439 | * @nr_grefs: number of grant references | |
4bac07c9 JF |
440 | * @vaddr: pointer to address to be filled out by mapping |
441 | * | |
ccc9d90a WL |
442 | * Map @nr_grefs pages of memory into this domain from another |
443 | * domain's grant table. xenbus_map_ring_valloc allocates @nr_grefs | |
444 | * pages of virtual address space, maps the pages to that address, and | |
445 | * sets *vaddr to that address. Returns 0 on success, and GNTST_* | |
446 | * (see xen/include/interface/grant_table.h) or -ENOMEM / -EINVAL on | |
447 | * error. If an error is returned, device will switch to | |
4bac07c9 JF |
448 | * XenbusStateClosing and the error message will be saved in XenStore. |
449 | */ | |
ccc9d90a WL |
450 | int xenbus_map_ring_valloc(struct xenbus_device *dev, grant_ref_t *gnt_refs, |
451 | unsigned int nr_grefs, void **vaddr) | |
2c5d37d3 | 452 | { |
ccc9d90a | 453 | return ring_ops->map(dev, gnt_refs, nr_grefs, vaddr); |
2c5d37d3 DDG |
454 | } |
455 | EXPORT_SYMBOL_GPL(xenbus_map_ring_valloc); | |
456 | ||
ccc9d90a WL |
457 | /* N.B. sizeof(phys_addr_t) doesn't always equal to sizeof(unsigned |
458 | * long), e.g. 32-on-64. Caller is responsible for preparing the | |
459 | * right array to feed into this function */ | |
460 | static int __xenbus_map_ring(struct xenbus_device *dev, | |
461 | grant_ref_t *gnt_refs, | |
462 | unsigned int nr_grefs, | |
463 | grant_handle_t *handles, | |
464 | phys_addr_t *addrs, | |
465 | unsigned int flags, | |
466 | bool *leaked) | |
467 | { | |
9cce2914 JG |
468 | struct gnttab_map_grant_ref map[XENBUS_MAX_RING_GRANTS]; |
469 | struct gnttab_unmap_grant_ref unmap[XENBUS_MAX_RING_GRANTS]; | |
ccc9d90a WL |
470 | int i, j; |
471 | int err = GNTST_okay; | |
472 | ||
9cce2914 | 473 | if (nr_grefs > XENBUS_MAX_RING_GRANTS) |
ccc9d90a WL |
474 | return -EINVAL; |
475 | ||
476 | for (i = 0; i < nr_grefs; i++) { | |
477 | memset(&map[i], 0, sizeof(map[i])); | |
478 | gnttab_set_map_op(&map[i], addrs[i], flags, gnt_refs[i], | |
479 | dev->otherend_id); | |
480 | handles[i] = INVALID_GRANT_HANDLE; | |
481 | } | |
482 | ||
483 | gnttab_batch_map(map, i); | |
484 | ||
485 | for (i = 0; i < nr_grefs; i++) { | |
486 | if (map[i].status != GNTST_okay) { | |
487 | err = map[i].status; | |
488 | xenbus_dev_fatal(dev, map[i].status, | |
489 | "mapping in shared page %d from domain %d", | |
490 | gnt_refs[i], dev->otherend_id); | |
491 | goto fail; | |
492 | } else | |
493 | handles[i] = map[i].handle; | |
494 | } | |
495 | ||
496 | return GNTST_okay; | |
497 | ||
498 | fail: | |
499 | for (i = j = 0; i < nr_grefs; i++) { | |
500 | if (handles[i] != INVALID_GRANT_HANDLE) { | |
501 | memset(&unmap[j], 0, sizeof(unmap[j])); | |
502 | gnttab_set_unmap_op(&unmap[j], (phys_addr_t)addrs[i], | |
503 | GNTMAP_host_map, handles[i]); | |
504 | j++; | |
505 | } | |
506 | } | |
507 | ||
508 | if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, unmap, j)) | |
509 | BUG(); | |
510 | ||
511 | *leaked = false; | |
512 | for (i = 0; i < j; i++) { | |
513 | if (unmap[i].status != GNTST_okay) { | |
514 | *leaked = true; | |
515 | break; | |
516 | } | |
517 | } | |
518 | ||
519 | return err; | |
520 | } | |
521 | ||
2c5d37d3 | 522 | static int xenbus_map_ring_valloc_pv(struct xenbus_device *dev, |
ccc9d90a WL |
523 | grant_ref_t *gnt_refs, |
524 | unsigned int nr_grefs, | |
525 | void **vaddr) | |
4bac07c9 | 526 | { |
2c5d37d3 | 527 | struct xenbus_map_node *node; |
4bac07c9 | 528 | struct vm_struct *area; |
9cce2914 JG |
529 | pte_t *ptes[XENBUS_MAX_RING_GRANTS]; |
530 | phys_addr_t phys_addrs[XENBUS_MAX_RING_GRANTS]; | |
ccc9d90a WL |
531 | int err = GNTST_okay; |
532 | int i; | |
533 | bool leaked; | |
4bac07c9 JF |
534 | |
535 | *vaddr = NULL; | |
536 | ||
9cce2914 | 537 | if (nr_grefs > XENBUS_MAX_RING_GRANTS) |
ccc9d90a WL |
538 | return -EINVAL; |
539 | ||
2c5d37d3 DDG |
540 | node = kzalloc(sizeof(*node), GFP_KERNEL); |
541 | if (!node) | |
542 | return -ENOMEM; | |
543 | ||
7d567928 | 544 | area = alloc_vm_area(XEN_PAGE_SIZE * nr_grefs, ptes); |
2c5d37d3 DDG |
545 | if (!area) { |
546 | kfree(node); | |
4bac07c9 | 547 | return -ENOMEM; |
2c5d37d3 | 548 | } |
4bac07c9 | 549 | |
ccc9d90a WL |
550 | for (i = 0; i < nr_grefs; i++) |
551 | phys_addrs[i] = arbitrary_virt_to_machine(ptes[i]).maddr; | |
4bac07c9 | 552 | |
ccc9d90a WL |
553 | err = __xenbus_map_ring(dev, gnt_refs, nr_grefs, node->handles, |
554 | phys_addrs, | |
555 | GNTMAP_host_map | GNTMAP_contains_pte, | |
556 | &leaked); | |
557 | if (err) | |
558 | goto failed; | |
4bac07c9 | 559 | |
ccc9d90a WL |
560 | node->nr_handles = nr_grefs; |
561 | node->pv.area = area; | |
2c5d37d3 DDG |
562 | |
563 | spin_lock(&xenbus_valloc_lock); | |
564 | list_add(&node->next, &xenbus_valloc_pages); | |
565 | spin_unlock(&xenbus_valloc_lock); | |
4bac07c9 JF |
566 | |
567 | *vaddr = area->addr; | |
568 | return 0; | |
ccc9d90a WL |
569 | |
570 | failed: | |
571 | if (!leaked) | |
572 | free_vm_area(area); | |
573 | else | |
574 | pr_alert("leaking VM area %p size %u page(s)", area, nr_grefs); | |
575 | ||
576 | kfree(node); | |
577 | return err; | |
4bac07c9 | 578 | } |
2c5d37d3 | 579 | |
89bf4b4e JG |
580 | struct map_ring_valloc_hvm |
581 | { | |
582 | unsigned int idx; | |
583 | ||
584 | /* Why do we need two arrays? See comment of __xenbus_map_ring */ | |
585 | phys_addr_t phys_addrs[XENBUS_MAX_RING_GRANTS]; | |
586 | unsigned long addrs[XENBUS_MAX_RING_GRANTS]; | |
587 | }; | |
588 | ||
589 | static void xenbus_map_ring_setup_grant_hvm(unsigned long gfn, | |
590 | unsigned int goffset, | |
591 | unsigned int len, | |
592 | void *data) | |
593 | { | |
594 | struct map_ring_valloc_hvm *info = data; | |
595 | unsigned long vaddr = (unsigned long)gfn_to_virt(gfn); | |
596 | ||
597 | info->phys_addrs[info->idx] = vaddr; | |
598 | info->addrs[info->idx] = vaddr; | |
599 | ||
600 | info->idx++; | |
601 | } | |
602 | ||
2c5d37d3 | 603 | static int xenbus_map_ring_valloc_hvm(struct xenbus_device *dev, |
ccc9d90a WL |
604 | grant_ref_t *gnt_ref, |
605 | unsigned int nr_grefs, | |
606 | void **vaddr) | |
2c5d37d3 DDG |
607 | { |
608 | struct xenbus_map_node *node; | |
609 | int err; | |
610 | void *addr; | |
ccc9d90a | 611 | bool leaked = false; |
89bf4b4e JG |
612 | struct map_ring_valloc_hvm info = { |
613 | .idx = 0, | |
614 | }; | |
615 | unsigned int nr_pages = XENBUS_PAGES(nr_grefs); | |
ccc9d90a | 616 | |
9cce2914 | 617 | if (nr_grefs > XENBUS_MAX_RING_GRANTS) |
ccc9d90a | 618 | return -EINVAL; |
2c5d37d3 DDG |
619 | |
620 | *vaddr = NULL; | |
621 | ||
622 | node = kzalloc(sizeof(*node), GFP_KERNEL); | |
623 | if (!node) | |
624 | return -ENOMEM; | |
625 | ||
89bf4b4e | 626 | err = alloc_xenballooned_pages(nr_pages, node->hvm.pages); |
2c5d37d3 DDG |
627 | if (err) |
628 | goto out_err; | |
629 | ||
89bf4b4e JG |
630 | gnttab_foreach_grant(node->hvm.pages, nr_grefs, |
631 | xenbus_map_ring_setup_grant_hvm, | |
632 | &info); | |
ccc9d90a WL |
633 | |
634 | err = __xenbus_map_ring(dev, gnt_ref, nr_grefs, node->handles, | |
89bf4b4e | 635 | info.phys_addrs, GNTMAP_host_map, &leaked); |
ccc9d90a | 636 | node->nr_handles = nr_grefs; |
2c5d37d3 | 637 | |
2c5d37d3 | 638 | if (err) |
ccc9d90a WL |
639 | goto out_free_ballooned_pages; |
640 | ||
89bf4b4e | 641 | addr = vmap(node->hvm.pages, nr_pages, VM_MAP | VM_IOREMAP, |
ccc9d90a WL |
642 | PAGE_KERNEL); |
643 | if (!addr) { | |
644 | err = -ENOMEM; | |
645 | goto out_xenbus_unmap_ring; | |
646 | } | |
647 | ||
648 | node->hvm.addr = addr; | |
2c5d37d3 DDG |
649 | |
650 | spin_lock(&xenbus_valloc_lock); | |
651 | list_add(&node->next, &xenbus_valloc_pages); | |
652 | spin_unlock(&xenbus_valloc_lock); | |
653 | ||
654 | *vaddr = addr; | |
655 | return 0; | |
656 | ||
ccc9d90a WL |
657 | out_xenbus_unmap_ring: |
658 | if (!leaked) | |
89bf4b4e | 659 | xenbus_unmap_ring(dev, node->handles, nr_grefs, info.addrs); |
ccc9d90a WL |
660 | else |
661 | pr_alert("leaking %p size %u page(s)", | |
89bf4b4e | 662 | addr, nr_pages); |
ccc9d90a WL |
663 | out_free_ballooned_pages: |
664 | if (!leaked) | |
89bf4b4e | 665 | free_xenballooned_pages(nr_pages, node->hvm.pages); |
8d0b8801 | 666 | out_err: |
2c5d37d3 DDG |
667 | kfree(node); |
668 | return err; | |
669 | } | |
4bac07c9 JF |
670 | |
671 | ||
672 | /** | |
673 | * xenbus_map_ring | |
674 | * @dev: xenbus device | |
ccc9d90a WL |
675 | * @gnt_refs: grant reference array |
676 | * @nr_grefs: number of grant reference | |
677 | * @handles: pointer to grant handle to be filled | |
678 | * @vaddrs: addresses to be mapped to | |
679 | * @leaked: fail to clean up a failed map, caller should not free vaddr | |
4bac07c9 | 680 | * |
ccc9d90a | 681 | * Map pages of memory into this domain from another domain's grant table. |
4bac07c9 | 682 | * xenbus_map_ring does not allocate the virtual address space (you must do |
ccc9d90a | 683 | * this yourself!). It only maps in the pages to the specified address. |
4bac07c9 | 684 | * Returns 0 on success, and GNTST_* (see xen/include/interface/grant_table.h) |
ccc9d90a WL |
685 | * or -ENOMEM / -EINVAL on error. If an error is returned, device will switch to |
686 | * XenbusStateClosing and the first error message will be saved in XenStore. | |
687 | * Further more if we fail to map the ring, caller should check @leaked. | |
688 | * If @leaked is not zero it means xenbus_map_ring fails to clean up, caller | |
689 | * should not free the address space of @vaddr. | |
4bac07c9 | 690 | */ |
ccc9d90a WL |
691 | int xenbus_map_ring(struct xenbus_device *dev, grant_ref_t *gnt_refs, |
692 | unsigned int nr_grefs, grant_handle_t *handles, | |
693 | unsigned long *vaddrs, bool *leaked) | |
4bac07c9 | 694 | { |
9cce2914 | 695 | phys_addr_t phys_addrs[XENBUS_MAX_RING_GRANTS]; |
ccc9d90a | 696 | int i; |
4bac07c9 | 697 | |
9cce2914 | 698 | if (nr_grefs > XENBUS_MAX_RING_GRANTS) |
ccc9d90a | 699 | return -EINVAL; |
4bac07c9 | 700 | |
ccc9d90a WL |
701 | for (i = 0; i < nr_grefs; i++) |
702 | phys_addrs[i] = (unsigned long)vaddrs[i]; | |
4bac07c9 | 703 | |
ccc9d90a WL |
704 | return __xenbus_map_ring(dev, gnt_refs, nr_grefs, handles, |
705 | phys_addrs, GNTMAP_host_map, leaked); | |
4bac07c9 JF |
706 | } |
707 | EXPORT_SYMBOL_GPL(xenbus_map_ring); | |
708 | ||
709 | ||
710 | /** | |
711 | * xenbus_unmap_ring_vfree | |
712 | * @dev: xenbus device | |
713 | * @vaddr: addr to unmap | |
714 | * | |
715 | * Based on Rusty Russell's skeleton driver's unmap_page. | |
716 | * Unmap a page of memory in this domain that was imported from another domain. | |
717 | * Use xenbus_unmap_ring_vfree if you mapped in your memory with | |
718 | * xenbus_map_ring_valloc (it will free the virtual address space). | |
719 | * Returns 0 on success and returns GNTST_* on error | |
720 | * (see xen/include/interface/grant_table.h). | |
721 | */ | |
722 | int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr) | |
723 | { | |
2c5d37d3 DDG |
724 | return ring_ops->unmap(dev, vaddr); |
725 | } | |
726 | EXPORT_SYMBOL_GPL(xenbus_unmap_ring_vfree); | |
727 | ||
728 | static int xenbus_unmap_ring_vfree_pv(struct xenbus_device *dev, void *vaddr) | |
729 | { | |
730 | struct xenbus_map_node *node; | |
9cce2914 | 731 | struct gnttab_unmap_grant_ref unmap[XENBUS_MAX_RING_GRANTS]; |
cd12909c | 732 | unsigned int level; |
ccc9d90a WL |
733 | int i; |
734 | bool leaked = false; | |
735 | int err; | |
4bac07c9 | 736 | |
2c5d37d3 DDG |
737 | spin_lock(&xenbus_valloc_lock); |
738 | list_for_each_entry(node, &xenbus_valloc_pages, next) { | |
ccc9d90a | 739 | if (node->pv.area->addr == vaddr) { |
2c5d37d3 DDG |
740 | list_del(&node->next); |
741 | goto found; | |
742 | } | |
4bac07c9 | 743 | } |
2c5d37d3 DDG |
744 | node = NULL; |
745 | found: | |
746 | spin_unlock(&xenbus_valloc_lock); | |
4bac07c9 | 747 | |
2c5d37d3 | 748 | if (!node) { |
4bac07c9 JF |
749 | xenbus_dev_error(dev, -ENOENT, |
750 | "can't find mapped virtual address %p", vaddr); | |
751 | return GNTST_bad_virt_addr; | |
752 | } | |
753 | ||
ccc9d90a WL |
754 | for (i = 0; i < node->nr_handles; i++) { |
755 | unsigned long addr; | |
756 | ||
757 | memset(&unmap[i], 0, sizeof(unmap[i])); | |
7d567928 | 758 | addr = (unsigned long)vaddr + (XEN_PAGE_SIZE * i); |
ccc9d90a WL |
759 | unmap[i].host_addr = arbitrary_virt_to_machine( |
760 | lookup_address(addr, &level)).maddr; | |
761 | unmap[i].dev_bus_addr = 0; | |
762 | unmap[i].handle = node->handles[i]; | |
763 | } | |
4bac07c9 | 764 | |
ccc9d90a | 765 | if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, unmap, i)) |
4bac07c9 JF |
766 | BUG(); |
767 | ||
ccc9d90a WL |
768 | err = GNTST_okay; |
769 | leaked = false; | |
770 | for (i = 0; i < node->nr_handles; i++) { | |
771 | if (unmap[i].status != GNTST_okay) { | |
772 | leaked = true; | |
773 | xenbus_dev_error(dev, unmap[i].status, | |
774 | "unmapping page at handle %d error %d", | |
775 | node->handles[i], unmap[i].status); | |
776 | err = unmap[i].status; | |
777 | break; | |
778 | } | |
779 | } | |
780 | ||
781 | if (!leaked) | |
782 | free_vm_area(node->pv.area); | |
4bac07c9 | 783 | else |
ccc9d90a WL |
784 | pr_alert("leaking VM area %p size %u page(s)", |
785 | node->pv.area, node->nr_handles); | |
4bac07c9 | 786 | |
2c5d37d3 | 787 | kfree(node); |
ccc9d90a | 788 | return err; |
4bac07c9 | 789 | } |
4bac07c9 | 790 | |
89bf4b4e JG |
791 | struct unmap_ring_vfree_hvm |
792 | { | |
793 | unsigned int idx; | |
794 | unsigned long addrs[XENBUS_MAX_RING_GRANTS]; | |
795 | }; | |
796 | ||
797 | static void xenbus_unmap_ring_setup_grant_hvm(unsigned long gfn, | |
798 | unsigned int goffset, | |
799 | unsigned int len, | |
800 | void *data) | |
801 | { | |
802 | struct unmap_ring_vfree_hvm *info = data; | |
803 | ||
804 | info->addrs[info->idx] = (unsigned long)gfn_to_virt(gfn); | |
805 | ||
806 | info->idx++; | |
807 | } | |
808 | ||
2c5d37d3 DDG |
809 | static int xenbus_unmap_ring_vfree_hvm(struct xenbus_device *dev, void *vaddr) |
810 | { | |
811 | int rv; | |
812 | struct xenbus_map_node *node; | |
813 | void *addr; | |
89bf4b4e JG |
814 | struct unmap_ring_vfree_hvm info = { |
815 | .idx = 0, | |
816 | }; | |
817 | unsigned int nr_pages; | |
2c5d37d3 DDG |
818 | |
819 | spin_lock(&xenbus_valloc_lock); | |
820 | list_for_each_entry(node, &xenbus_valloc_pages, next) { | |
ccc9d90a | 821 | addr = node->hvm.addr; |
2c5d37d3 DDG |
822 | if (addr == vaddr) { |
823 | list_del(&node->next); | |
824 | goto found; | |
825 | } | |
826 | } | |
5ac08001 | 827 | node = addr = NULL; |
2c5d37d3 DDG |
828 | found: |
829 | spin_unlock(&xenbus_valloc_lock); | |
830 | ||
831 | if (!node) { | |
832 | xenbus_dev_error(dev, -ENOENT, | |
833 | "can't find mapped virtual address %p", vaddr); | |
834 | return GNTST_bad_virt_addr; | |
835 | } | |
836 | ||
89bf4b4e JG |
837 | nr_pages = XENBUS_PAGES(node->nr_handles); |
838 | ||
839 | gnttab_foreach_grant(node->hvm.pages, node->nr_handles, | |
840 | xenbus_unmap_ring_setup_grant_hvm, | |
841 | &info); | |
2c5d37d3 | 842 | |
ccc9d90a | 843 | rv = xenbus_unmap_ring(dev, node->handles, node->nr_handles, |
89bf4b4e | 844 | info.addrs); |
c22fe519 | 845 | if (!rv) { |
ccc9d90a | 846 | vunmap(vaddr); |
89bf4b4e | 847 | free_xenballooned_pages(nr_pages, node->hvm.pages); |
c22fe519 | 848 | } |
2c5d37d3 | 849 | else |
89bf4b4e | 850 | WARN(1, "Leaking %p, size %u page(s)\n", vaddr, nr_pages); |
2c5d37d3 DDG |
851 | |
852 | kfree(node); | |
853 | return rv; | |
854 | } | |
4bac07c9 JF |
855 | |
856 | /** | |
857 | * xenbus_unmap_ring | |
858 | * @dev: xenbus device | |
ccc9d90a WL |
859 | * @handles: grant handle array |
860 | * @nr_handles: number of handles in the array | |
861 | * @vaddrs: addresses to unmap | |
4bac07c9 | 862 | * |
ccc9d90a | 863 | * Unmap memory in this domain that was imported from another domain. |
4bac07c9 JF |
864 | * Returns 0 on success and returns GNTST_* on error |
865 | * (see xen/include/interface/grant_table.h). | |
866 | */ | |
867 | int xenbus_unmap_ring(struct xenbus_device *dev, | |
ccc9d90a WL |
868 | grant_handle_t *handles, unsigned int nr_handles, |
869 | unsigned long *vaddrs) | |
4bac07c9 | 870 | { |
9cce2914 | 871 | struct gnttab_unmap_grant_ref unmap[XENBUS_MAX_RING_GRANTS]; |
ccc9d90a WL |
872 | int i; |
873 | int err; | |
2946a52a | 874 | |
9cce2914 | 875 | if (nr_handles > XENBUS_MAX_RING_GRANTS) |
ccc9d90a | 876 | return -EINVAL; |
4bac07c9 | 877 | |
ccc9d90a WL |
878 | for (i = 0; i < nr_handles; i++) |
879 | gnttab_set_unmap_op(&unmap[i], vaddrs[i], | |
880 | GNTMAP_host_map, handles[i]); | |
881 | ||
882 | if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, unmap, i)) | |
4bac07c9 JF |
883 | BUG(); |
884 | ||
ccc9d90a WL |
885 | err = GNTST_okay; |
886 | for (i = 0; i < nr_handles; i++) { | |
887 | if (unmap[i].status != GNTST_okay) { | |
888 | xenbus_dev_error(dev, unmap[i].status, | |
889 | "unmapping page at handle %d error %d", | |
890 | handles[i], unmap[i].status); | |
891 | err = unmap[i].status; | |
892 | break; | |
893 | } | |
894 | } | |
4bac07c9 | 895 | |
ccc9d90a | 896 | return err; |
4bac07c9 JF |
897 | } |
898 | EXPORT_SYMBOL_GPL(xenbus_unmap_ring); | |
899 | ||
900 | ||
901 | /** | |
902 | * xenbus_read_driver_state | |
903 | * @path: path for driver | |
904 | * | |
905 | * Return the state of the driver rooted at the given store path, or | |
906 | * XenbusStateUnknown if no state can be read. | |
907 | */ | |
908 | enum xenbus_state xenbus_read_driver_state(const char *path) | |
909 | { | |
910 | enum xenbus_state result; | |
911 | int err = xenbus_gather(XBT_NIL, path, "state", "%d", &result, NULL); | |
912 | if (err) | |
913 | result = XenbusStateUnknown; | |
914 | ||
915 | return result; | |
916 | } | |
917 | EXPORT_SYMBOL_GPL(xenbus_read_driver_state); | |
2c5d37d3 DDG |
918 | |
919 | static const struct xenbus_ring_ops ring_ops_pv = { | |
920 | .map = xenbus_map_ring_valloc_pv, | |
921 | .unmap = xenbus_unmap_ring_vfree_pv, | |
922 | }; | |
923 | ||
924 | static const struct xenbus_ring_ops ring_ops_hvm = { | |
925 | .map = xenbus_map_ring_valloc_hvm, | |
926 | .unmap = xenbus_unmap_ring_vfree_hvm, | |
927 | }; | |
928 | ||
929 | void __init xenbus_ring_ops_init(void) | |
930 | { | |
be3e9cf3 | 931 | if (!xen_feature(XENFEAT_auto_translated_physmap)) |
2c5d37d3 DDG |
932 | ring_ops = &ring_ops_pv; |
933 | else | |
934 | ring_ops = &ring_ops_hvm; | |
935 | } |