1 /******************************************************************************
2 * grant_table.c
3 *
4 * Granting foreign access to our memory reservation.
5 *
6 * Copyright (c) 2005-2006, Christopher Clark
7 * Copyright (c) 2004-2005, K A Fraser
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License version 2
11 * as published by the Free Software Foundation; or, when distributed
12 * separately from the Linux kernel or incorporated into other
13 * software packages, subject to the following license:
14 *
15 * Permission is hereby granted, free of charge, to any person obtaining a copy
16 * of this source file (the "Software"), to deal in the Software without
17 * restriction, including without limitation the rights to use, copy, modify,
18 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
19 * and to permit persons to whom the Software is furnished to do so, subject to
20 * the following conditions:
21 *
22 * The above copyright notice and this permission notice shall be included in
23 * all copies or substantial portions of the Software.
24 *
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
30 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
31 * IN THE SOFTWARE.
32 */
33
34 #include <linux/module.h>
35 #include <linux/sched.h>
36 #include <linux/mm.h>
37 #include <linux/slab.h>
38 #include <linux/vmalloc.h>
39 #include <linux/uaccess.h>
40 #include <linux/io.h>
41
42 #include <xen/xen.h>
43 #include <xen/interface/xen.h>
44 #include <xen/page.h>
45 #include <xen/grant_table.h>
46 #include <xen/interface/memory.h>
47 #include <xen/hvc-console.h>
48 #include <asm/xen/hypercall.h>
49
50 #include <asm/pgtable.h>
51 #include <asm/sync_bitops.h>
52
53 /* External tools reserve first few grant table entries. */
54 #define NR_RESERVED_ENTRIES 8
55 #define GNTTAB_LIST_END 0xffffffff
56
57 static grant_ref_t **gnttab_list;
58 static unsigned int nr_grant_frames;
59 static unsigned int boot_max_nr_grant_frames;
60 static int gnttab_free_count;
61 static grant_ref_t gnttab_free_head;
62 static DEFINE_SPINLOCK(gnttab_list_lock);
63 unsigned long xen_hvm_resume_frames;
64 EXPORT_SYMBOL_GPL(xen_hvm_resume_frames);
65
66 static union {
67 struct grant_entry_v1 *v1;
68 union grant_entry_v2 *v2;
69 void *addr;
70 } gnttab_shared;
71
72 /*This is a structure of function pointers for grant table*/
73 struct gnttab_ops {
74 /*
75 * Mapping a list of frames for storing grant entries. Frames parameter
76 * is used to store grant table address when grant table being setup,
77 * nr_gframes is the number of frames to map grant table. Returning
78 * GNTST_okay means success and negative value means failure.
79 */
80 int (*map_frames)(unsigned long *frames, unsigned int nr_gframes);
81 /*
82 * Release a list of frames which are mapped in map_frames for grant
83 * entry status.
84 */
85 void (*unmap_frames)(void);
86 /*
87 * Introducing a valid entry into the grant table, granting the frame of
88 * this grant entry to domain for accessing or transfering. Ref
89 * parameter is reference of this introduced grant entry, domid is id of
90 * granted domain, frame is the page frame to be granted, and flags is
91 * status of the grant entry to be updated.
92 */
93 void (*update_entry)(grant_ref_t ref, domid_t domid,
94 unsigned long frame, unsigned flags);
95 /*
96 * Stop granting a grant entry to domain for accessing. Ref parameter is
97 * reference of a grant entry whose grant access will be stopped,
98 * readonly is not in use in this function. If the grant entry is
99 * currently mapped for reading or writing, just return failure(==0)
100 * directly and don't tear down the grant access. Otherwise, stop grant
101 * access for this entry and return success(==1).
102 */
103 int (*end_foreign_access_ref)(grant_ref_t ref, int readonly);
104 /*
105 * Stop granting a grant entry to domain for transfer. Ref parameter is
106 * reference of a grant entry whose grant transfer will be stopped. If
107 * tranfer has not started, just reclaim the grant entry and return
108 * failure(==0). Otherwise, wait for the transfer to complete and then
109 * return the frame.
110 */
111 unsigned long (*end_foreign_transfer_ref)(grant_ref_t ref);
112 /*
113 * Query the status of a grant entry. Ref parameter is reference of
114 * queried grant entry, return value is the status of queried entry.
115 * Detailed status(writing/reading) can be gotten from the return value
116 * by bit operations.
117 */
118 int (*query_foreign_access)(grant_ref_t ref);
119 /*
120 * Grant a domain to access a range of bytes within the page referred by
121 * an available grant entry. Ref parameter is reference of a grant entry
122 * which will be sub-page accessed, domid is id of grantee domain, frame
123 * is frame address of subpage grant, flags is grant type and flag
124 * information, page_off is offset of the range of bytes, and length is
125 * length of bytes to be accessed.
126 */
127 void (*update_subpage_entry)(grant_ref_t ref, domid_t domid,
128 unsigned long frame, int flags,
129 unsigned page_off, unsigned length);
130 /*
131 * Redirect an available grant entry on domain A to another grant
132 * reference of domain B, then allow domain C to use grant reference
133 * of domain B transitively. Ref parameter is an available grant entry
134 * reference on domain A, domid is id of domain C which accesses grant
135 * entry transitively, flags is grant type and flag information,
136 * trans_domid is id of domain B whose grant entry is finally accessed
137 * transitively, trans_gref is grant entry transitive reference of
138 * domain B.
139 */
140 void (*update_trans_entry)(grant_ref_t ref, domid_t domid, int flags,
141 domid_t trans_domid, grant_ref_t trans_gref);
142 };
143
144 static struct gnttab_ops *gnttab_interface;
145
146 /*This reflects status of grant entries, so act as a global value*/
147 static grant_status_t *grstatus;
148
149 static int grant_table_version;
150 static int grefs_per_grant_frame;
151
152 static struct gnttab_free_callback *gnttab_free_callback_list;
153
154 static int gnttab_expand(unsigned int req_entries);
155
156 #define RPP (PAGE_SIZE / sizeof(grant_ref_t))
157 #define SPP (PAGE_SIZE / sizeof(grant_status_t))
158
__gnttab_entry(grant_ref_t entry)159 static inline grant_ref_t *__gnttab_entry(grant_ref_t entry)
160 {
161 return &gnttab_list[(entry) / RPP][(entry) % RPP];
162 }
163 /* This can be used as an l-value */
164 #define gnttab_entry(entry) (*__gnttab_entry(entry))
165
get_free_entries(unsigned count)166 static int get_free_entries(unsigned count)
167 {
168 unsigned long flags;
169 int ref, rc = 0;
170 grant_ref_t head;
171
172 spin_lock_irqsave(&gnttab_list_lock, flags);
173
174 if ((gnttab_free_count < count) &&
175 ((rc = gnttab_expand(count - gnttab_free_count)) < 0)) {
176 spin_unlock_irqrestore(&gnttab_list_lock, flags);
177 return rc;
178 }
179
180 ref = head = gnttab_free_head;
181 gnttab_free_count -= count;
182 while (count-- > 1)
183 head = gnttab_entry(head);
184 gnttab_free_head = gnttab_entry(head);
185 gnttab_entry(head) = GNTTAB_LIST_END;
186
187 spin_unlock_irqrestore(&gnttab_list_lock, flags);
188
189 return ref;
190 }
191
do_free_callbacks(void)192 static void do_free_callbacks(void)
193 {
194 struct gnttab_free_callback *callback, *next;
195
196 callback = gnttab_free_callback_list;
197 gnttab_free_callback_list = NULL;
198
199 while (callback != NULL) {
200 next = callback->next;
201 if (gnttab_free_count >= callback->count) {
202 callback->next = NULL;
203 callback->fn(callback->arg);
204 } else {
205 callback->next = gnttab_free_callback_list;
206 gnttab_free_callback_list = callback;
207 }
208 callback = next;
209 }
210 }
211
check_free_callbacks(void)212 static inline void check_free_callbacks(void)
213 {
214 if (unlikely(gnttab_free_callback_list))
215 do_free_callbacks();
216 }
217
put_free_entry(grant_ref_t ref)218 static void put_free_entry(grant_ref_t ref)
219 {
220 unsigned long flags;
221 spin_lock_irqsave(&gnttab_list_lock, flags);
222 gnttab_entry(ref) = gnttab_free_head;
223 gnttab_free_head = ref;
224 gnttab_free_count++;
225 check_free_callbacks();
226 spin_unlock_irqrestore(&gnttab_list_lock, flags);
227 }
228
229 /*
230 * Following applies to gnttab_update_entry_v1 and gnttab_update_entry_v2.
231 * Introducing a valid entry into the grant table:
232 * 1. Write ent->domid.
233 * 2. Write ent->frame:
234 * GTF_permit_access: Frame to which access is permitted.
235 * GTF_accept_transfer: Pseudo-phys frame slot being filled by new
236 * frame, or zero if none.
237 * 3. Write memory barrier (WMB).
238 * 4. Write ent->flags, inc. valid type.
239 */
gnttab_update_entry_v1(grant_ref_t ref,domid_t domid,unsigned long frame,unsigned flags)240 static void gnttab_update_entry_v1(grant_ref_t ref, domid_t domid,
241 unsigned long frame, unsigned flags)
242 {
243 gnttab_shared.v1[ref].domid = domid;
244 gnttab_shared.v1[ref].frame = frame;
245 wmb();
246 gnttab_shared.v1[ref].flags = flags;
247 }
248
gnttab_update_entry_v2(grant_ref_t ref,domid_t domid,unsigned long frame,unsigned flags)249 static void gnttab_update_entry_v2(grant_ref_t ref, domid_t domid,
250 unsigned long frame, unsigned flags)
251 {
252 gnttab_shared.v2[ref].hdr.domid = domid;
253 gnttab_shared.v2[ref].full_page.frame = frame;
254 wmb();
255 gnttab_shared.v2[ref].hdr.flags = GTF_permit_access | flags;
256 }
257
258 /*
259 * Public grant-issuing interface functions
260 */
gnttab_grant_foreign_access_ref(grant_ref_t ref,domid_t domid,unsigned long frame,int readonly)261 void gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid,
262 unsigned long frame, int readonly)
263 {
264 gnttab_interface->update_entry(ref, domid, frame,
265 GTF_permit_access | (readonly ? GTF_readonly : 0));
266 }
267 EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access_ref);
268
gnttab_grant_foreign_access(domid_t domid,unsigned long frame,int readonly)269 int gnttab_grant_foreign_access(domid_t domid, unsigned long frame,
270 int readonly)
271 {
272 int ref;
273
274 ref = get_free_entries(1);
275 if (unlikely(ref < 0))
276 return -ENOSPC;
277
278 gnttab_grant_foreign_access_ref(ref, domid, frame, readonly);
279
280 return ref;
281 }
282 EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access);
283
gnttab_update_subpage_entry_v2(grant_ref_t ref,domid_t domid,unsigned long frame,int flags,unsigned page_off,unsigned length)284 void gnttab_update_subpage_entry_v2(grant_ref_t ref, domid_t domid,
285 unsigned long frame, int flags,
286 unsigned page_off,
287 unsigned length)
288 {
289 gnttab_shared.v2[ref].sub_page.frame = frame;
290 gnttab_shared.v2[ref].sub_page.page_off = page_off;
291 gnttab_shared.v2[ref].sub_page.length = length;
292 gnttab_shared.v2[ref].hdr.domid = domid;
293 wmb();
294 gnttab_shared.v2[ref].hdr.flags =
295 GTF_permit_access | GTF_sub_page | flags;
296 }
297
gnttab_grant_foreign_access_subpage_ref(grant_ref_t ref,domid_t domid,unsigned long frame,int flags,unsigned page_off,unsigned length)298 int gnttab_grant_foreign_access_subpage_ref(grant_ref_t ref, domid_t domid,
299 unsigned long frame, int flags,
300 unsigned page_off,
301 unsigned length)
302 {
303 if (flags & (GTF_accept_transfer | GTF_reading |
304 GTF_writing | GTF_transitive))
305 return -EPERM;
306
307 if (gnttab_interface->update_subpage_entry == NULL)
308 return -ENOSYS;
309
310 gnttab_interface->update_subpage_entry(ref, domid, frame, flags,
311 page_off, length);
312
313 return 0;
314 }
315 EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access_subpage_ref);
316
gnttab_grant_foreign_access_subpage(domid_t domid,unsigned long frame,int flags,unsigned page_off,unsigned length)317 int gnttab_grant_foreign_access_subpage(domid_t domid, unsigned long frame,
318 int flags, unsigned page_off,
319 unsigned length)
320 {
321 int ref, rc;
322
323 ref = get_free_entries(1);
324 if (unlikely(ref < 0))
325 return -ENOSPC;
326
327 rc = gnttab_grant_foreign_access_subpage_ref(ref, domid, frame, flags,
328 page_off, length);
329 if (rc < 0) {
330 put_free_entry(ref);
331 return rc;
332 }
333
334 return ref;
335 }
336 EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access_subpage);
337
gnttab_subpage_grants_available(void)338 bool gnttab_subpage_grants_available(void)
339 {
340 return gnttab_interface->update_subpage_entry != NULL;
341 }
342 EXPORT_SYMBOL_GPL(gnttab_subpage_grants_available);
343
gnttab_update_trans_entry_v2(grant_ref_t ref,domid_t domid,int flags,domid_t trans_domid,grant_ref_t trans_gref)344 void gnttab_update_trans_entry_v2(grant_ref_t ref, domid_t domid,
345 int flags, domid_t trans_domid,
346 grant_ref_t trans_gref)
347 {
348 gnttab_shared.v2[ref].transitive.trans_domid = trans_domid;
349 gnttab_shared.v2[ref].transitive.gref = trans_gref;
350 gnttab_shared.v2[ref].hdr.domid = domid;
351 wmb();
352 gnttab_shared.v2[ref].hdr.flags =
353 GTF_permit_access | GTF_transitive | flags;
354 }
355
gnttab_grant_foreign_access_trans_ref(grant_ref_t ref,domid_t domid,int flags,domid_t trans_domid,grant_ref_t trans_gref)356 int gnttab_grant_foreign_access_trans_ref(grant_ref_t ref, domid_t domid,
357 int flags, domid_t trans_domid,
358 grant_ref_t trans_gref)
359 {
360 if (flags & (GTF_accept_transfer | GTF_reading |
361 GTF_writing | GTF_sub_page))
362 return -EPERM;
363
364 if (gnttab_interface->update_trans_entry == NULL)
365 return -ENOSYS;
366
367 gnttab_interface->update_trans_entry(ref, domid, flags, trans_domid,
368 trans_gref);
369
370 return 0;
371 }
372 EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access_trans_ref);
373
gnttab_grant_foreign_access_trans(domid_t domid,int flags,domid_t trans_domid,grant_ref_t trans_gref)374 int gnttab_grant_foreign_access_trans(domid_t domid, int flags,
375 domid_t trans_domid,
376 grant_ref_t trans_gref)
377 {
378 int ref, rc;
379
380 ref = get_free_entries(1);
381 if (unlikely(ref < 0))
382 return -ENOSPC;
383
384 rc = gnttab_grant_foreign_access_trans_ref(ref, domid, flags,
385 trans_domid, trans_gref);
386 if (rc < 0) {
387 put_free_entry(ref);
388 return rc;
389 }
390
391 return ref;
392 }
393 EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access_trans);
394
gnttab_trans_grants_available(void)395 bool gnttab_trans_grants_available(void)
396 {
397 return gnttab_interface->update_trans_entry != NULL;
398 }
399 EXPORT_SYMBOL_GPL(gnttab_trans_grants_available);
400
gnttab_query_foreign_access_v1(grant_ref_t ref)401 static int gnttab_query_foreign_access_v1(grant_ref_t ref)
402 {
403 return gnttab_shared.v1[ref].flags & (GTF_reading|GTF_writing);
404 }
405
gnttab_query_foreign_access_v2(grant_ref_t ref)406 static int gnttab_query_foreign_access_v2(grant_ref_t ref)
407 {
408 return grstatus[ref] & (GTF_reading|GTF_writing);
409 }
410
gnttab_query_foreign_access(grant_ref_t ref)411 int gnttab_query_foreign_access(grant_ref_t ref)
412 {
413 return gnttab_interface->query_foreign_access(ref);
414 }
415 EXPORT_SYMBOL_GPL(gnttab_query_foreign_access);
416
gnttab_end_foreign_access_ref_v1(grant_ref_t ref,int readonly)417 static int gnttab_end_foreign_access_ref_v1(grant_ref_t ref, int readonly)
418 {
419 u16 flags, nflags;
420 u16 *pflags;
421
422 pflags = &gnttab_shared.v1[ref].flags;
423 nflags = *pflags;
424 do {
425 flags = nflags;
426 if (flags & (GTF_reading|GTF_writing)) {
427 printk(KERN_ALERT "WARNING: g.e. still in use!\n");
428 return 0;
429 }
430 } while ((nflags = sync_cmpxchg(pflags, flags, 0)) != flags);
431
432 return 1;
433 }
434
gnttab_end_foreign_access_ref_v2(grant_ref_t ref,int readonly)435 static int gnttab_end_foreign_access_ref_v2(grant_ref_t ref, int readonly)
436 {
437 gnttab_shared.v2[ref].hdr.flags = 0;
438 mb();
439 if (grstatus[ref] & (GTF_reading|GTF_writing)) {
440 return 0;
441 } else {
442 /* The read of grstatus needs to have acquire
443 semantics. On x86, reads already have
444 that, and we just need to protect against
445 compiler reorderings. On other
446 architectures we may need a full
447 barrier. */
448 #ifdef CONFIG_X86
449 barrier();
450 #else
451 mb();
452 #endif
453 }
454
455 return 1;
456 }
457
gnttab_end_foreign_access_ref(grant_ref_t ref,int readonly)458 int gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly)
459 {
460 return gnttab_interface->end_foreign_access_ref(ref, readonly);
461 }
462 EXPORT_SYMBOL_GPL(gnttab_end_foreign_access_ref);
463
gnttab_end_foreign_access(grant_ref_t ref,int readonly,unsigned long page)464 void gnttab_end_foreign_access(grant_ref_t ref, int readonly,
465 unsigned long page)
466 {
467 if (gnttab_end_foreign_access_ref(ref, readonly)) {
468 put_free_entry(ref);
469 if (page != 0)
470 free_page(page);
471 } else {
472 /* XXX This needs to be fixed so that the ref and page are
473 placed on a list to be freed up later. */
474 printk(KERN_WARNING
475 "WARNING: leaking g.e. and page still in use!\n");
476 }
477 }
478 EXPORT_SYMBOL_GPL(gnttab_end_foreign_access);
479
gnttab_grant_foreign_transfer(domid_t domid,unsigned long pfn)480 int gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn)
481 {
482 int ref;
483
484 ref = get_free_entries(1);
485 if (unlikely(ref < 0))
486 return -ENOSPC;
487 gnttab_grant_foreign_transfer_ref(ref, domid, pfn);
488
489 return ref;
490 }
491 EXPORT_SYMBOL_GPL(gnttab_grant_foreign_transfer);
492
gnttab_grant_foreign_transfer_ref(grant_ref_t ref,domid_t domid,unsigned long pfn)493 void gnttab_grant_foreign_transfer_ref(grant_ref_t ref, domid_t domid,
494 unsigned long pfn)
495 {
496 gnttab_interface->update_entry(ref, domid, pfn, GTF_accept_transfer);
497 }
498 EXPORT_SYMBOL_GPL(gnttab_grant_foreign_transfer_ref);
499
gnttab_end_foreign_transfer_ref_v1(grant_ref_t ref)500 static unsigned long gnttab_end_foreign_transfer_ref_v1(grant_ref_t ref)
501 {
502 unsigned long frame;
503 u16 flags;
504 u16 *pflags;
505
506 pflags = &gnttab_shared.v1[ref].flags;
507
508 /*
509 * If a transfer is not even yet started, try to reclaim the grant
510 * reference and return failure (== 0).
511 */
512 while (!((flags = *pflags) & GTF_transfer_committed)) {
513 if (sync_cmpxchg(pflags, flags, 0) == flags)
514 return 0;
515 cpu_relax();
516 }
517
518 /* If a transfer is in progress then wait until it is completed. */
519 while (!(flags & GTF_transfer_completed)) {
520 flags = *pflags;
521 cpu_relax();
522 }
523
524 rmb(); /* Read the frame number /after/ reading completion status. */
525 frame = gnttab_shared.v1[ref].frame;
526 BUG_ON(frame == 0);
527
528 return frame;
529 }
530
gnttab_end_foreign_transfer_ref_v2(grant_ref_t ref)531 static unsigned long gnttab_end_foreign_transfer_ref_v2(grant_ref_t ref)
532 {
533 unsigned long frame;
534 u16 flags;
535 u16 *pflags;
536
537 pflags = &gnttab_shared.v2[ref].hdr.flags;
538
539 /*
540 * If a transfer is not even yet started, try to reclaim the grant
541 * reference and return failure (== 0).
542 */
543 while (!((flags = *pflags) & GTF_transfer_committed)) {
544 if (sync_cmpxchg(pflags, flags, 0) == flags)
545 return 0;
546 cpu_relax();
547 }
548
549 /* If a transfer is in progress then wait until it is completed. */
550 while (!(flags & GTF_transfer_completed)) {
551 flags = *pflags;
552 cpu_relax();
553 }
554
555 rmb(); /* Read the frame number /after/ reading completion status. */
556 frame = gnttab_shared.v2[ref].full_page.frame;
557 BUG_ON(frame == 0);
558
559 return frame;
560 }
561
gnttab_end_foreign_transfer_ref(grant_ref_t ref)562 unsigned long gnttab_end_foreign_transfer_ref(grant_ref_t ref)
563 {
564 return gnttab_interface->end_foreign_transfer_ref(ref);
565 }
566 EXPORT_SYMBOL_GPL(gnttab_end_foreign_transfer_ref);
567
gnttab_end_foreign_transfer(grant_ref_t ref)568 unsigned long gnttab_end_foreign_transfer(grant_ref_t ref)
569 {
570 unsigned long frame = gnttab_end_foreign_transfer_ref(ref);
571 put_free_entry(ref);
572 return frame;
573 }
574 EXPORT_SYMBOL_GPL(gnttab_end_foreign_transfer);
575
gnttab_free_grant_reference(grant_ref_t ref)576 void gnttab_free_grant_reference(grant_ref_t ref)
577 {
578 put_free_entry(ref);
579 }
580 EXPORT_SYMBOL_GPL(gnttab_free_grant_reference);
581
gnttab_free_grant_references(grant_ref_t head)582 void gnttab_free_grant_references(grant_ref_t head)
583 {
584 grant_ref_t ref;
585 unsigned long flags;
586 int count = 1;
587 if (head == GNTTAB_LIST_END)
588 return;
589 spin_lock_irqsave(&gnttab_list_lock, flags);
590 ref = head;
591 while (gnttab_entry(ref) != GNTTAB_LIST_END) {
592 ref = gnttab_entry(ref);
593 count++;
594 }
595 gnttab_entry(ref) = gnttab_free_head;
596 gnttab_free_head = head;
597 gnttab_free_count += count;
598 check_free_callbacks();
599 spin_unlock_irqrestore(&gnttab_list_lock, flags);
600 }
601 EXPORT_SYMBOL_GPL(gnttab_free_grant_references);
602
gnttab_alloc_grant_references(u16 count,grant_ref_t * head)603 int gnttab_alloc_grant_references(u16 count, grant_ref_t *head)
604 {
605 int h = get_free_entries(count);
606
607 if (h < 0)
608 return -ENOSPC;
609
610 *head = h;
611
612 return 0;
613 }
614 EXPORT_SYMBOL_GPL(gnttab_alloc_grant_references);
615
gnttab_empty_grant_references(const grant_ref_t * private_head)616 int gnttab_empty_grant_references(const grant_ref_t *private_head)
617 {
618 return (*private_head == GNTTAB_LIST_END);
619 }
620 EXPORT_SYMBOL_GPL(gnttab_empty_grant_references);
621
gnttab_claim_grant_reference(grant_ref_t * private_head)622 int gnttab_claim_grant_reference(grant_ref_t *private_head)
623 {
624 grant_ref_t g = *private_head;
625 if (unlikely(g == GNTTAB_LIST_END))
626 return -ENOSPC;
627 *private_head = gnttab_entry(g);
628 return g;
629 }
630 EXPORT_SYMBOL_GPL(gnttab_claim_grant_reference);
631
gnttab_release_grant_reference(grant_ref_t * private_head,grant_ref_t release)632 void gnttab_release_grant_reference(grant_ref_t *private_head,
633 grant_ref_t release)
634 {
635 gnttab_entry(release) = *private_head;
636 *private_head = release;
637 }
638 EXPORT_SYMBOL_GPL(gnttab_release_grant_reference);
639
gnttab_request_free_callback(struct gnttab_free_callback * callback,void (* fn)(void *),void * arg,u16 count)640 void gnttab_request_free_callback(struct gnttab_free_callback *callback,
641 void (*fn)(void *), void *arg, u16 count)
642 {
643 unsigned long flags;
644 struct gnttab_free_callback *cb;
645
646 spin_lock_irqsave(&gnttab_list_lock, flags);
647
648 /* Check if the callback is already on the list */
649 cb = gnttab_free_callback_list;
650 while (cb) {
651 if (cb == callback)
652 goto out;
653 cb = cb->next;
654 }
655
656 callback->fn = fn;
657 callback->arg = arg;
658 callback->count = count;
659 callback->next = gnttab_free_callback_list;
660 gnttab_free_callback_list = callback;
661 check_free_callbacks();
662 out:
663 spin_unlock_irqrestore(&gnttab_list_lock, flags);
664 }
665 EXPORT_SYMBOL_GPL(gnttab_request_free_callback);
666
gnttab_cancel_free_callback(struct gnttab_free_callback * callback)667 void gnttab_cancel_free_callback(struct gnttab_free_callback *callback)
668 {
669 struct gnttab_free_callback **pcb;
670 unsigned long flags;
671
672 spin_lock_irqsave(&gnttab_list_lock, flags);
673 for (pcb = &gnttab_free_callback_list; *pcb; pcb = &(*pcb)->next) {
674 if (*pcb == callback) {
675 *pcb = callback->next;
676 break;
677 }
678 }
679 spin_unlock_irqrestore(&gnttab_list_lock, flags);
680 }
681 EXPORT_SYMBOL_GPL(gnttab_cancel_free_callback);
682
grow_gnttab_list(unsigned int more_frames)683 static int grow_gnttab_list(unsigned int more_frames)
684 {
685 unsigned int new_nr_grant_frames, extra_entries, i;
686 unsigned int nr_glist_frames, new_nr_glist_frames;
687
688 BUG_ON(grefs_per_grant_frame == 0);
689
690 new_nr_grant_frames = nr_grant_frames + more_frames;
691 extra_entries = more_frames * grefs_per_grant_frame;
692
693 nr_glist_frames = (nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP;
694 new_nr_glist_frames =
695 (new_nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP;
696 for (i = nr_glist_frames; i < new_nr_glist_frames; i++) {
697 gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_ATOMIC);
698 if (!gnttab_list[i])
699 goto grow_nomem;
700 }
701
702
703 for (i = grefs_per_grant_frame * nr_grant_frames;
704 i < grefs_per_grant_frame * new_nr_grant_frames - 1; i++)
705 gnttab_entry(i) = i + 1;
706
707 gnttab_entry(i) = gnttab_free_head;
708 gnttab_free_head = grefs_per_grant_frame * nr_grant_frames;
709 gnttab_free_count += extra_entries;
710
711 nr_grant_frames = new_nr_grant_frames;
712
713 check_free_callbacks();
714
715 return 0;
716
717 grow_nomem:
718 for ( ; i >= nr_glist_frames; i--)
719 free_page((unsigned long) gnttab_list[i]);
720 return -ENOMEM;
721 }
722
__max_nr_grant_frames(void)723 static unsigned int __max_nr_grant_frames(void)
724 {
725 struct gnttab_query_size query;
726 int rc;
727
728 query.dom = DOMID_SELF;
729
730 rc = HYPERVISOR_grant_table_op(GNTTABOP_query_size, &query, 1);
731 if ((rc < 0) || (query.status != GNTST_okay))
732 return 4; /* Legacy max supported number of frames */
733
734 return query.max_nr_frames;
735 }
736
gnttab_max_grant_frames(void)737 unsigned int gnttab_max_grant_frames(void)
738 {
739 unsigned int xen_max = __max_nr_grant_frames();
740
741 if (xen_max > boot_max_nr_grant_frames)
742 return boot_max_nr_grant_frames;
743 return xen_max;
744 }
745 EXPORT_SYMBOL_GPL(gnttab_max_grant_frames);
746
gnttab_map_refs(struct gnttab_map_grant_ref * map_ops,struct gnttab_map_grant_ref * kmap_ops,struct page ** pages,unsigned int count)747 int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
748 struct gnttab_map_grant_ref *kmap_ops,
749 struct page **pages, unsigned int count)
750 {
751 int i, ret;
752 pte_t *pte;
753 unsigned long mfn;
754
755 ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map_ops, count);
756 if (ret)
757 return ret;
758
759 if (xen_feature(XENFEAT_auto_translated_physmap))
760 return ret;
761
762 for (i = 0; i < count; i++) {
763 /* Do not add to override if the map failed. */
764 if (map_ops[i].status)
765 continue;
766
767 if (map_ops[i].flags & GNTMAP_contains_pte) {
768 pte = (pte_t *) (mfn_to_virt(PFN_DOWN(map_ops[i].host_addr)) +
769 (map_ops[i].host_addr & ~PAGE_MASK));
770 mfn = pte_mfn(*pte);
771 } else {
772 mfn = PFN_DOWN(map_ops[i].dev_bus_addr);
773 }
774 ret = m2p_add_override(mfn, pages[i], kmap_ops ?
775 &kmap_ops[i] : NULL);
776 if (ret)
777 return ret;
778 }
779
780 return ret;
781 }
782 EXPORT_SYMBOL_GPL(gnttab_map_refs);
783
gnttab_unmap_refs(struct gnttab_unmap_grant_ref * unmap_ops,struct gnttab_map_grant_ref * kmap_ops,struct page ** pages,unsigned int count)784 int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
785 struct gnttab_map_grant_ref *kmap_ops,
786 struct page **pages, unsigned int count)
787 {
788 int i, ret;
789
790 ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, unmap_ops, count);
791 if (ret)
792 return ret;
793
794 if (xen_feature(XENFEAT_auto_translated_physmap))
795 return ret;
796
797 for (i = 0; i < count; i++) {
798 ret = m2p_remove_override(pages[i], kmap_ops ?
799 &kmap_ops[i] : NULL);
800 if (ret)
801 return ret;
802 }
803
804 return ret;
805 }
806 EXPORT_SYMBOL_GPL(gnttab_unmap_refs);
807
nr_status_frames(unsigned nr_grant_frames)808 static unsigned nr_status_frames(unsigned nr_grant_frames)
809 {
810 BUG_ON(grefs_per_grant_frame == 0);
811 return (nr_grant_frames * grefs_per_grant_frame + SPP - 1) / SPP;
812 }
813
gnttab_map_frames_v1(unsigned long * frames,unsigned int nr_gframes)814 static int gnttab_map_frames_v1(unsigned long *frames, unsigned int nr_gframes)
815 {
816 int rc;
817
818 rc = arch_gnttab_map_shared(frames, nr_gframes,
819 gnttab_max_grant_frames(),
820 &gnttab_shared.addr);
821 BUG_ON(rc);
822
823 return 0;
824 }
825
gnttab_unmap_frames_v1(void)826 static void gnttab_unmap_frames_v1(void)
827 {
828 arch_gnttab_unmap(gnttab_shared.addr, nr_grant_frames);
829 }
830
gnttab_map_frames_v2(unsigned long * frames,unsigned int nr_gframes)831 static int gnttab_map_frames_v2(unsigned long *frames, unsigned int nr_gframes)
832 {
833 uint64_t *sframes;
834 unsigned int nr_sframes;
835 struct gnttab_get_status_frames getframes;
836 int rc;
837
838 nr_sframes = nr_status_frames(nr_gframes);
839
840 /* No need for kzalloc as it is initialized in following hypercall
841 * GNTTABOP_get_status_frames.
842 */
843 sframes = kmalloc(nr_sframes * sizeof(uint64_t), GFP_ATOMIC);
844 if (!sframes)
845 return -ENOMEM;
846
847 getframes.dom = DOMID_SELF;
848 getframes.nr_frames = nr_sframes;
849 set_xen_guest_handle(getframes.frame_list, sframes);
850
851 rc = HYPERVISOR_grant_table_op(GNTTABOP_get_status_frames,
852 &getframes, 1);
853 if (rc == -ENOSYS) {
854 kfree(sframes);
855 return -ENOSYS;
856 }
857
858 BUG_ON(rc || getframes.status);
859
860 rc = arch_gnttab_map_status(sframes, nr_sframes,
861 nr_status_frames(gnttab_max_grant_frames()),
862 &grstatus);
863 BUG_ON(rc);
864 kfree(sframes);
865
866 rc = arch_gnttab_map_shared(frames, nr_gframes,
867 gnttab_max_grant_frames(),
868 &gnttab_shared.addr);
869 BUG_ON(rc);
870
871 return 0;
872 }
873
gnttab_unmap_frames_v2(void)874 static void gnttab_unmap_frames_v2(void)
875 {
876 arch_gnttab_unmap(gnttab_shared.addr, nr_grant_frames);
877 arch_gnttab_unmap(grstatus, nr_status_frames(nr_grant_frames));
878 }
879
gnttab_map(unsigned int start_idx,unsigned int end_idx)880 static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
881 {
882 struct gnttab_setup_table setup;
883 unsigned long *frames;
884 unsigned int nr_gframes = end_idx + 1;
885 int rc;
886
887 if (xen_hvm_domain()) {
888 struct xen_add_to_physmap xatp;
889 unsigned int i = end_idx;
890 rc = 0;
891 /*
892 * Loop backwards, so that the first hypercall has the largest
893 * index, ensuring that the table will grow only once.
894 */
895 do {
896 xatp.domid = DOMID_SELF;
897 xatp.idx = i;
898 xatp.space = XENMAPSPACE_grant_table;
899 xatp.gpfn = (xen_hvm_resume_frames >> PAGE_SHIFT) + i;
900 rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp);
901 if (rc != 0) {
902 printk(KERN_WARNING
903 "grant table add_to_physmap failed, err=%d\n", rc);
904 break;
905 }
906 } while (i-- > start_idx);
907
908 return rc;
909 }
910
911 /* No need for kzalloc as it is initialized in following hypercall
912 * GNTTABOP_setup_table.
913 */
914 frames = kmalloc(nr_gframes * sizeof(unsigned long), GFP_ATOMIC);
915 if (!frames)
916 return -ENOMEM;
917
918 setup.dom = DOMID_SELF;
919 setup.nr_frames = nr_gframes;
920 set_xen_guest_handle(setup.frame_list, frames);
921
922 rc = HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
923 if (rc == -ENOSYS) {
924 kfree(frames);
925 return -ENOSYS;
926 }
927
928 BUG_ON(rc || setup.status);
929
930 rc = gnttab_interface->map_frames(frames, nr_gframes);
931
932 kfree(frames);
933
934 return rc;
935 }
936
937 static struct gnttab_ops gnttab_v1_ops = {
938 .map_frames = gnttab_map_frames_v1,
939 .unmap_frames = gnttab_unmap_frames_v1,
940 .update_entry = gnttab_update_entry_v1,
941 .end_foreign_access_ref = gnttab_end_foreign_access_ref_v1,
942 .end_foreign_transfer_ref = gnttab_end_foreign_transfer_ref_v1,
943 .query_foreign_access = gnttab_query_foreign_access_v1,
944 };
945
946 static struct gnttab_ops gnttab_v2_ops = {
947 .map_frames = gnttab_map_frames_v2,
948 .unmap_frames = gnttab_unmap_frames_v2,
949 .update_entry = gnttab_update_entry_v2,
950 .end_foreign_access_ref = gnttab_end_foreign_access_ref_v2,
951 .end_foreign_transfer_ref = gnttab_end_foreign_transfer_ref_v2,
952 .query_foreign_access = gnttab_query_foreign_access_v2,
953 .update_subpage_entry = gnttab_update_subpage_entry_v2,
954 .update_trans_entry = gnttab_update_trans_entry_v2,
955 };
956
gnttab_request_version(void)957 static void gnttab_request_version(void)
958 {
959 int rc;
960 struct gnttab_set_version gsv;
961
962 if (xen_hvm_domain())
963 gsv.version = 1;
964 else
965 gsv.version = 2;
966 rc = HYPERVISOR_grant_table_op(GNTTABOP_set_version, &gsv, 1);
967 if (rc == 0 && gsv.version == 2) {
968 grant_table_version = 2;
969 grefs_per_grant_frame = PAGE_SIZE / sizeof(union grant_entry_v2);
970 gnttab_interface = &gnttab_v2_ops;
971 } else if (grant_table_version == 2) {
972 /*
973 * If we've already used version 2 features,
974 * but then suddenly discover that they're not
975 * available (e.g. migrating to an older
976 * version of Xen), almost unbounded badness
977 * can happen.
978 */
979 panic("we need grant tables version 2, but only version 1 is available");
980 } else {
981 grant_table_version = 1;
982 grefs_per_grant_frame = PAGE_SIZE / sizeof(struct grant_entry_v1);
983 gnttab_interface = &gnttab_v1_ops;
984 }
985 printk(KERN_INFO "Grant tables using version %d layout.\n",
986 grant_table_version);
987 }
988
gnttab_setup(void)989 static int gnttab_setup(void)
990 {
991 unsigned int max_nr_gframes;
992
993 max_nr_gframes = gnttab_max_grant_frames();
994 if (max_nr_gframes < nr_grant_frames)
995 return -ENOSYS;
996
997 if (xen_pv_domain())
998 return gnttab_map(0, nr_grant_frames - 1);
999
1000 if (gnttab_shared.addr == NULL) {
1001 gnttab_shared.addr = ioremap(xen_hvm_resume_frames,
1002 PAGE_SIZE * max_nr_gframes);
1003 if (gnttab_shared.addr == NULL) {
1004 printk(KERN_WARNING
1005 "Failed to ioremap gnttab share frames!");
1006 return -ENOMEM;
1007 }
1008 }
1009
1010 gnttab_map(0, nr_grant_frames - 1);
1011
1012 return 0;
1013 }
1014
gnttab_resume(void)1015 int gnttab_resume(void)
1016 {
1017 gnttab_request_version();
1018 return gnttab_setup();
1019 }
1020
gnttab_suspend(void)1021 int gnttab_suspend(void)
1022 {
1023 gnttab_interface->unmap_frames();
1024 return 0;
1025 }
1026
gnttab_expand(unsigned int req_entries)1027 static int gnttab_expand(unsigned int req_entries)
1028 {
1029 int rc;
1030 unsigned int cur, extra;
1031
1032 BUG_ON(grefs_per_grant_frame == 0);
1033 cur = nr_grant_frames;
1034 extra = ((req_entries + (grefs_per_grant_frame-1)) /
1035 grefs_per_grant_frame);
1036 if (cur + extra > gnttab_max_grant_frames())
1037 return -ENOSPC;
1038
1039 rc = gnttab_map(cur, cur + extra - 1);
1040 if (rc == 0)
1041 rc = grow_gnttab_list(extra);
1042
1043 return rc;
1044 }
1045
gnttab_init(void)1046 int gnttab_init(void)
1047 {
1048 int i;
1049 unsigned int max_nr_glist_frames, nr_glist_frames;
1050 unsigned int nr_init_grefs;
1051 int ret;
1052
1053 gnttab_request_version();
1054 nr_grant_frames = 1;
1055 boot_max_nr_grant_frames = __max_nr_grant_frames();
1056
1057 /* Determine the maximum number of frames required for the
1058 * grant reference free list on the current hypervisor.
1059 */
1060 BUG_ON(grefs_per_grant_frame == 0);
1061 max_nr_glist_frames = (boot_max_nr_grant_frames *
1062 grefs_per_grant_frame / RPP);
1063
1064 gnttab_list = kmalloc(max_nr_glist_frames * sizeof(grant_ref_t *),
1065 GFP_KERNEL);
1066 if (gnttab_list == NULL)
1067 return -ENOMEM;
1068
1069 nr_glist_frames = (nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP;
1070 for (i = 0; i < nr_glist_frames; i++) {
1071 gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_KERNEL);
1072 if (gnttab_list[i] == NULL) {
1073 ret = -ENOMEM;
1074 goto ini_nomem;
1075 }
1076 }
1077
1078 if (gnttab_setup() < 0) {
1079 ret = -ENODEV;
1080 goto ini_nomem;
1081 }
1082
1083 nr_init_grefs = nr_grant_frames * grefs_per_grant_frame;
1084
1085 for (i = NR_RESERVED_ENTRIES; i < nr_init_grefs - 1; i++)
1086 gnttab_entry(i) = i + 1;
1087
1088 gnttab_entry(nr_init_grefs - 1) = GNTTAB_LIST_END;
1089 gnttab_free_count = nr_init_grefs - NR_RESERVED_ENTRIES;
1090 gnttab_free_head = NR_RESERVED_ENTRIES;
1091
1092 printk("Grant table initialized\n");
1093 return 0;
1094
1095 ini_nomem:
1096 for (i--; i >= 0; i--)
1097 free_page((unsigned long)gnttab_list[i]);
1098 kfree(gnttab_list);
1099 return ret;
1100 }
1101 EXPORT_SYMBOL_GPL(gnttab_init);
1102
__gnttab_init(void)1103 static int __devinit __gnttab_init(void)
1104 {
1105 /* Delay grant-table initialization in the PV on HVM case */
1106 if (xen_hvm_domain())
1107 return 0;
1108
1109 if (!xen_pv_domain())
1110 return -ENODEV;
1111
1112 return gnttab_init();
1113 }
1114
1115 core_initcall(__gnttab_init);
1116