blob: 3275bde6ad75340d6773b8b2c955e510afa5c12d [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001/******************************************************************************
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
57static grant_ref_t **gnttab_list;
58static unsigned int nr_grant_frames;
59static unsigned int boot_max_nr_grant_frames;
60static int gnttab_free_count;
61static grant_ref_t gnttab_free_head;
62static DEFINE_SPINLOCK(gnttab_list_lock);
63unsigned long xen_hvm_resume_frames;
64EXPORT_SYMBOL_GPL(xen_hvm_resume_frames);
65
66static 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*/
73struct 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
144static struct gnttab_ops *gnttab_interface;
145
146/*This reflects status of grant entries, so act as a global value*/
147static grant_status_t *grstatus;
148
149static int grant_table_version;
150static int grefs_per_grant_frame;
151
152static struct gnttab_free_callback *gnttab_free_callback_list;
153
154static 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
159static 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
166static 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
192static 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
212static inline void check_free_callbacks(void)
213{
214 if (unlikely(gnttab_free_callback_list))
215 do_free_callbacks();
216}
217
218static 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 */
240static 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
249static 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 */
261void 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}
267EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access_ref);
268
269int 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}
282EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access);
283
284void 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
298int 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}
315EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access_subpage_ref);
316
317int 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}
336EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access_subpage);
337
338bool gnttab_subpage_grants_available(void)
339{
340 return gnttab_interface->update_subpage_entry != NULL;
341}
342EXPORT_SYMBOL_GPL(gnttab_subpage_grants_available);
343
344void 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
356int 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}
372EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access_trans_ref);
373
374int 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}
393EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access_trans);
394
395bool gnttab_trans_grants_available(void)
396{
397 return gnttab_interface->update_trans_entry != NULL;
398}
399EXPORT_SYMBOL_GPL(gnttab_trans_grants_available);
400
401static int gnttab_query_foreign_access_v1(grant_ref_t ref)
402{
403 return gnttab_shared.v1[ref].flags & (GTF_reading|GTF_writing);
404}
405
406static int gnttab_query_foreign_access_v2(grant_ref_t ref)
407{
408 return grstatus[ref] & (GTF_reading|GTF_writing);
409}
410
411int gnttab_query_foreign_access(grant_ref_t ref)
412{
413 return gnttab_interface->query_foreign_access(ref);
414}
415EXPORT_SYMBOL_GPL(gnttab_query_foreign_access);
416
417static 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
435static 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
458int gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly)
459{
460 return gnttab_interface->end_foreign_access_ref(ref, readonly);
461}
462EXPORT_SYMBOL_GPL(gnttab_end_foreign_access_ref);
463
464void 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}
478EXPORT_SYMBOL_GPL(gnttab_end_foreign_access);
479
480int 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}
491EXPORT_SYMBOL_GPL(gnttab_grant_foreign_transfer);
492
493void 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}
498EXPORT_SYMBOL_GPL(gnttab_grant_foreign_transfer_ref);
499
500static 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
531static 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
562unsigned long gnttab_end_foreign_transfer_ref(grant_ref_t ref)
563{
564 return gnttab_interface->end_foreign_transfer_ref(ref);
565}
566EXPORT_SYMBOL_GPL(gnttab_end_foreign_transfer_ref);
567
568unsigned 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}
574EXPORT_SYMBOL_GPL(gnttab_end_foreign_transfer);
575
576void gnttab_free_grant_reference(grant_ref_t ref)
577{
578 put_free_entry(ref);
579}
580EXPORT_SYMBOL_GPL(gnttab_free_grant_reference);
581
582void 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}
601EXPORT_SYMBOL_GPL(gnttab_free_grant_references);
602
603int 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}
614EXPORT_SYMBOL_GPL(gnttab_alloc_grant_references);
615
616int gnttab_empty_grant_references(const grant_ref_t *private_head)
617{
618 return (*private_head == GNTTAB_LIST_END);
619}
620EXPORT_SYMBOL_GPL(gnttab_empty_grant_references);
621
622int 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}
630EXPORT_SYMBOL_GPL(gnttab_claim_grant_reference);
631
632void 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}
638EXPORT_SYMBOL_GPL(gnttab_release_grant_reference);
639
640void 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();
662out:
663 spin_unlock_irqrestore(&gnttab_list_lock, flags);
664}
665EXPORT_SYMBOL_GPL(gnttab_request_free_callback);
666
667void 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}
681EXPORT_SYMBOL_GPL(gnttab_cancel_free_callback);
682
683static 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
717grow_nomem:
718 for ( ; i >= nr_glist_frames; i--)
719 free_page((unsigned long) gnttab_list[i]);
720 return -ENOMEM;
721}
722
723static 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
737unsigned 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}
745EXPORT_SYMBOL_GPL(gnttab_max_grant_frames);
746
747int 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}
782EXPORT_SYMBOL_GPL(gnttab_map_refs);
783
784int 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}
806EXPORT_SYMBOL_GPL(gnttab_unmap_refs);
807
808static 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
814static 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
826static void gnttab_unmap_frames_v1(void)
827{
828 arch_gnttab_unmap(gnttab_shared.addr, nr_grant_frames);
829}
830
831static 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
874static 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
880static 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
937static 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
946static 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
957static 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
989static 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
1015int gnttab_resume(void)
1016{
1017 gnttab_request_version();
1018 return gnttab_setup();
1019}
1020
1021int gnttab_suspend(void)
1022{
1023 gnttab_interface->unmap_frames();
1024 return 0;
1025}
1026
1027static 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
1046int 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}
1101EXPORT_SYMBOL_GPL(gnttab_init);
1102
1103static 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
1115core_initcall(__gnttab_init);