]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/xen/grant-table.c
xen/granttable: Grant tables V2 implementation
[mirror_ubuntu-artful-kernel.git] / drivers / xen / grant-table.c
CommitLineData
ad9a8612
JF
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>
5a0e3ad6 37#include <linux/slab.h>
ad9a8612
JF
38#include <linux/vmalloc.h>
39#include <linux/uaccess.h>
183d03cc 40#include <linux/io.h>
ad9a8612 41
1ccbf534 42#include <xen/xen.h>
ad9a8612
JF
43#include <xen/interface/xen.h>
44#include <xen/page.h>
45#include <xen/grant_table.h>
183d03cc 46#include <xen/interface/memory.h>
85ff6acb 47#include <xen/hvc-console.h>
ecbf29cd 48#include <asm/xen/hypercall.h>
ad9a8612
JF
49
50#include <asm/pgtable.h>
51#include <asm/sync_bitops.h>
52
53
54/* External tools reserve first few grant table entries. */
55#define NR_RESERVED_ENTRIES 8
56#define GNTTAB_LIST_END 0xffffffff
85ff6acb
AL
57#define GREFS_PER_GRANT_FRAME \
58(grant_table_version == 1 ? \
59(PAGE_SIZE / sizeof(struct grant_entry_v1)) : \
60(PAGE_SIZE / sizeof(union grant_entry_v2)))
ad9a8612
JF
61
62static grant_ref_t **gnttab_list;
63static unsigned int nr_grant_frames;
64static unsigned int boot_max_nr_grant_frames;
65static int gnttab_free_count;
66static grant_ref_t gnttab_free_head;
67static DEFINE_SPINLOCK(gnttab_list_lock);
183d03cc
SS
68unsigned long xen_hvm_resume_frames;
69EXPORT_SYMBOL_GPL(xen_hvm_resume_frames);
ad9a8612 70
0f9f5a95
AL
71static union {
72 struct grant_entry_v1 *v1;
85ff6acb 73 union grant_entry_v2 *v2;
0f9f5a95
AL
74 void *addr;
75} gnttab_shared;
76
77/*This is a structure of function pointers for grant table*/
78struct gnttab_ops {
79 /*
80 * Mapping a list of frames for storing grant entries. First input
81 * parameter is used to storing grant table address when grant table
82 * being setup, second parameter is the number of frames to map grant
83 * table. Returning GNTST_okay means success and negative value means
84 * failure.
85 */
86 int (*map_frames)(unsigned long *, unsigned int);
87 /*
88 * Release a list of frames which are mapped in map_frames for grant
89 * entry status.
90 */
91 void (*unmap_frames)(void);
92 /*
93 * Introducing a valid entry into the grant table, granting the frame
94 * of this grant entry to domain for accessing, or transfering, or
95 * transitively accessing. First input parameter is reference of this
96 * introduced grant entry, second one is domid of granted domain, third
97 * one is the frame to be granted, and the last one is status of the
98 * grant entry to be updated.
99 */
100 void (*update_entry)(grant_ref_t, domid_t, unsigned long, unsigned);
101 /*
102 * Stop granting a grant entry to domain for accessing. First input
103 * parameter is reference of a grant entry whose grant access will be
104 * stopped, second one is not in use now. If the grant entry is
105 * currently mapped for reading or writing, just return failure(==0)
106 * directly and don't tear down the grant access. Otherwise, stop grant
107 * access for this entry and return success(==1).
108 */
109 int (*end_foreign_access_ref)(grant_ref_t, int);
110 /*
111 * Stop granting a grant entry to domain for transfer. If tranfer has
112 * not started, just reclaim the grant entry and return failure(==0).
113 * Otherwise, wait for the transfer to complete and then return the
114 * frame.
115 */
116 unsigned long (*end_foreign_transfer_ref)(grant_ref_t);
117 /*
118 * Query the status of a grant entry. Input parameter is reference of
119 * queried grant entry, return value is the status of queried entry.
120 * Detailed status(writing/reading) can be gotten from the return value
121 * by bit operations.
122 */
123 int (*query_foreign_access)(grant_ref_t);
124};
125
126static struct gnttab_ops *gnttab_interface;
127
85ff6acb
AL
128/*This reflects status of grant entries, so act as a global value*/
129static grant_status_t *grstatus;
130
0f9f5a95 131static int grant_table_version;
ad9a8612
JF
132
133static struct gnttab_free_callback *gnttab_free_callback_list;
134
135static int gnttab_expand(unsigned int req_entries);
136
137#define RPP (PAGE_SIZE / sizeof(grant_ref_t))
85ff6acb 138#define SPP (PAGE_SIZE / sizeof(grant_status_t))
ad9a8612
JF
139
140static inline grant_ref_t *__gnttab_entry(grant_ref_t entry)
141{
142 return &gnttab_list[(entry) / RPP][(entry) % RPP];
143}
144/* This can be used as an l-value */
145#define gnttab_entry(entry) (*__gnttab_entry(entry))
146
147static int get_free_entries(unsigned count)
148{
149 unsigned long flags;
272800dc 150 int ref, rc = 0;
ad9a8612
JF
151 grant_ref_t head;
152
153 spin_lock_irqsave(&gnttab_list_lock, flags);
154
155 if ((gnttab_free_count < count) &&
156 ((rc = gnttab_expand(count - gnttab_free_count)) < 0)) {
157 spin_unlock_irqrestore(&gnttab_list_lock, flags);
158 return rc;
159 }
160
161 ref = head = gnttab_free_head;
162 gnttab_free_count -= count;
163 while (count-- > 1)
164 head = gnttab_entry(head);
165 gnttab_free_head = gnttab_entry(head);
166 gnttab_entry(head) = GNTTAB_LIST_END;
167
168 spin_unlock_irqrestore(&gnttab_list_lock, flags);
169
170 return ref;
171}
172
173static void do_free_callbacks(void)
174{
175 struct gnttab_free_callback *callback, *next;
176
177 callback = gnttab_free_callback_list;
178 gnttab_free_callback_list = NULL;
179
180 while (callback != NULL) {
181 next = callback->next;
182 if (gnttab_free_count >= callback->count) {
183 callback->next = NULL;
184 callback->fn(callback->arg);
185 } else {
186 callback->next = gnttab_free_callback_list;
187 gnttab_free_callback_list = callback;
188 }
189 callback = next;
190 }
191}
192
193static inline void check_free_callbacks(void)
194{
195 if (unlikely(gnttab_free_callback_list))
196 do_free_callbacks();
197}
198
199static void put_free_entry(grant_ref_t ref)
200{
201 unsigned long flags;
202 spin_lock_irqsave(&gnttab_list_lock, flags);
203 gnttab_entry(ref) = gnttab_free_head;
204 gnttab_free_head = ref;
205 gnttab_free_count++;
206 check_free_callbacks();
207 spin_unlock_irqrestore(&gnttab_list_lock, flags);
208}
209
0f9f5a95 210/*
85ff6acb 211 * Following applies to gnttab_update_entry_v1 and gnttab_update_entry_v2.
0f9f5a95
AL
212 * Introducing a valid entry into the grant table:
213 * 1. Write ent->domid.
214 * 2. Write ent->frame:
215 * GTF_permit_access: Frame to which access is permitted.
216 * GTF_accept_transfer: Pseudo-phys frame slot being filled by new
217 * frame, or zero if none.
218 * 3. Write memory barrier (WMB).
219 * 4. Write ent->flags, inc. valid type.
220 */
221static void gnttab_update_entry_v1(grant_ref_t ref, domid_t domid,
222 unsigned long frame, unsigned flags)
ad9a8612 223{
0f9f5a95
AL
224 gnttab_shared.v1[ref].domid = domid;
225 gnttab_shared.v1[ref].frame = frame;
ad9a8612 226 wmb();
0f9f5a95 227 gnttab_shared.v1[ref].flags = flags;
ad9a8612
JF
228}
229
85ff6acb
AL
230static void gnttab_update_entry_v2(grant_ref_t ref, domid_t domid,
231 unsigned long frame, unsigned flags)
232{
233 gnttab_shared.v2[ref].hdr.domid = domid;
234 gnttab_shared.v2[ref].full_page.frame = frame;
235 wmb();
236 gnttab_shared.v2[ref].hdr.flags = GTF_permit_access | flags;
237}
238
ad9a8612
JF
239/*
240 * Public grant-issuing interface functions
241 */
242void gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid,
243 unsigned long frame, int readonly)
244{
0f9f5a95 245 gnttab_interface->update_entry(ref, domid, frame,
ad9a8612
JF
246 GTF_permit_access | (readonly ? GTF_readonly : 0));
247}
248EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access_ref);
249
250int gnttab_grant_foreign_access(domid_t domid, unsigned long frame,
251 int readonly)
252{
253 int ref;
254
255 ref = get_free_entries(1);
256 if (unlikely(ref < 0))
257 return -ENOSPC;
258
259 gnttab_grant_foreign_access_ref(ref, domid, frame, readonly);
260
261 return ref;
262}
263EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access);
264
0f9f5a95 265static int gnttab_query_foreign_access_v1(grant_ref_t ref)
ad9a8612 266{
0f9f5a95
AL
267 return gnttab_shared.v1[ref].flags & (GTF_reading|GTF_writing);
268}
ad9a8612 269
85ff6acb
AL
270static int gnttab_query_foreign_access_v2(grant_ref_t ref)
271{
272 return grstatus[ref] & (GTF_reading|GTF_writing);
273}
274
0f9f5a95
AL
275int gnttab_query_foreign_access(grant_ref_t ref)
276{
277 return gnttab_interface->query_foreign_access(ref);
ad9a8612
JF
278}
279EXPORT_SYMBOL_GPL(gnttab_query_foreign_access);
280
0f9f5a95 281static int gnttab_end_foreign_access_ref_v1(grant_ref_t ref, int readonly)
ad9a8612
JF
282{
283 u16 flags, nflags;
b1e495b2 284 u16 *pflags;
ad9a8612 285
b1e495b2
AL
286 pflags = &gnttab_shared.v1[ref].flags;
287 nflags = *pflags;
ad9a8612
JF
288 do {
289 flags = nflags;
290 if (flags & (GTF_reading|GTF_writing)) {
291 printk(KERN_ALERT "WARNING: g.e. still in use!\n");
292 return 0;
293 }
b1e495b2 294 } while ((nflags = sync_cmpxchg(pflags, flags, 0)) != flags);
ad9a8612
JF
295
296 return 1;
297}
0f9f5a95 298
85ff6acb
AL
299static int gnttab_end_foreign_access_ref_v2(grant_ref_t ref, int readonly)
300{
301 gnttab_shared.v2[ref].hdr.flags = 0;
302 mb();
303 if (grstatus[ref] & (GTF_reading|GTF_writing)) {
304 return 0;
305 } else {
306 /* The read of grstatus needs to have acquire
307 semantics. On x86, reads already have
308 that, and we just need to protect against
309 compiler reorderings. On other
310 architectures we may need a full
311 barrier. */
312#ifdef CONFIG_X86
313 barrier();
314#else
315 mb();
316#endif
317 }
318
319 return 1;
320}
321
0f9f5a95
AL
322int gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly)
323{
324 return gnttab_interface->end_foreign_access_ref(ref, readonly);
325}
ad9a8612
JF
326EXPORT_SYMBOL_GPL(gnttab_end_foreign_access_ref);
327
328void gnttab_end_foreign_access(grant_ref_t ref, int readonly,
329 unsigned long page)
330{
331 if (gnttab_end_foreign_access_ref(ref, readonly)) {
332 put_free_entry(ref);
333 if (page != 0)
334 free_page(page);
335 } else {
336 /* XXX This needs to be fixed so that the ref and page are
337 placed on a list to be freed up later. */
338 printk(KERN_WARNING
339 "WARNING: leaking g.e. and page still in use!\n");
340 }
341}
342EXPORT_SYMBOL_GPL(gnttab_end_foreign_access);
343
344int gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn)
345{
346 int ref;
347
348 ref = get_free_entries(1);
349 if (unlikely(ref < 0))
350 return -ENOSPC;
351 gnttab_grant_foreign_transfer_ref(ref, domid, pfn);
352
353 return ref;
354}
355EXPORT_SYMBOL_GPL(gnttab_grant_foreign_transfer);
356
357void gnttab_grant_foreign_transfer_ref(grant_ref_t ref, domid_t domid,
358 unsigned long pfn)
359{
0f9f5a95 360 gnttab_interface->update_entry(ref, domid, pfn, GTF_accept_transfer);
ad9a8612
JF
361}
362EXPORT_SYMBOL_GPL(gnttab_grant_foreign_transfer_ref);
363
0f9f5a95 364static unsigned long gnttab_end_foreign_transfer_ref_v1(grant_ref_t ref)
ad9a8612
JF
365{
366 unsigned long frame;
367 u16 flags;
b1e495b2
AL
368 u16 *pflags;
369
370 pflags = &gnttab_shared.v1[ref].flags;
ad9a8612
JF
371
372 /*
373 * If a transfer is not even yet started, try to reclaim the grant
374 * reference and return failure (== 0).
375 */
b1e495b2
AL
376 while (!((flags = *pflags) & GTF_transfer_committed)) {
377 if (sync_cmpxchg(pflags, flags, 0) == flags)
ad9a8612
JF
378 return 0;
379 cpu_relax();
380 }
381
382 /* If a transfer is in progress then wait until it is completed. */
383 while (!(flags & GTF_transfer_completed)) {
b1e495b2 384 flags = *pflags;
ad9a8612
JF
385 cpu_relax();
386 }
387
388 rmb(); /* Read the frame number /after/ reading completion status. */
0f9f5a95 389 frame = gnttab_shared.v1[ref].frame;
ad9a8612
JF
390 BUG_ON(frame == 0);
391
392 return frame;
393}
0f9f5a95 394
85ff6acb
AL
395static unsigned long gnttab_end_foreign_transfer_ref_v2(grant_ref_t ref)
396{
397 unsigned long frame;
398 u16 flags;
399 u16 *pflags;
400
401 pflags = &gnttab_shared.v2[ref].hdr.flags;
402
403 /*
404 * If a transfer is not even yet started, try to reclaim the grant
405 * reference and return failure (== 0).
406 */
407 while (!((flags = *pflags) & GTF_transfer_committed)) {
408 if (sync_cmpxchg(pflags, flags, 0) == flags)
409 return 0;
410 cpu_relax();
411 }
412
413 /* If a transfer is in progress then wait until it is completed. */
414 while (!(flags & GTF_transfer_completed)) {
415 flags = *pflags;
416 cpu_relax();
417 }
418
419 rmb(); /* Read the frame number /after/ reading completion status. */
420 frame = gnttab_shared.v2[ref].full_page.frame;
421 BUG_ON(frame == 0);
422
423 return frame;
424}
425
0f9f5a95
AL
426unsigned long gnttab_end_foreign_transfer_ref(grant_ref_t ref)
427{
428 return gnttab_interface->end_foreign_transfer_ref(ref);
429}
ad9a8612
JF
430EXPORT_SYMBOL_GPL(gnttab_end_foreign_transfer_ref);
431
432unsigned long gnttab_end_foreign_transfer(grant_ref_t ref)
433{
434 unsigned long frame = gnttab_end_foreign_transfer_ref(ref);
435 put_free_entry(ref);
436 return frame;
437}
438EXPORT_SYMBOL_GPL(gnttab_end_foreign_transfer);
439
440void gnttab_free_grant_reference(grant_ref_t ref)
441{
442 put_free_entry(ref);
443}
444EXPORT_SYMBOL_GPL(gnttab_free_grant_reference);
445
446void gnttab_free_grant_references(grant_ref_t head)
447{
448 grant_ref_t ref;
449 unsigned long flags;
450 int count = 1;
451 if (head == GNTTAB_LIST_END)
452 return;
453 spin_lock_irqsave(&gnttab_list_lock, flags);
454 ref = head;
455 while (gnttab_entry(ref) != GNTTAB_LIST_END) {
456 ref = gnttab_entry(ref);
457 count++;
458 }
459 gnttab_entry(ref) = gnttab_free_head;
460 gnttab_free_head = head;
461 gnttab_free_count += count;
462 check_free_callbacks();
463 spin_unlock_irqrestore(&gnttab_list_lock, flags);
464}
465EXPORT_SYMBOL_GPL(gnttab_free_grant_references);
466
467int gnttab_alloc_grant_references(u16 count, grant_ref_t *head)
468{
469 int h = get_free_entries(count);
470
471 if (h < 0)
472 return -ENOSPC;
473
474 *head = h;
475
476 return 0;
477}
478EXPORT_SYMBOL_GPL(gnttab_alloc_grant_references);
479
480int gnttab_empty_grant_references(const grant_ref_t *private_head)
481{
482 return (*private_head == GNTTAB_LIST_END);
483}
484EXPORT_SYMBOL_GPL(gnttab_empty_grant_references);
485
486int gnttab_claim_grant_reference(grant_ref_t *private_head)
487{
488 grant_ref_t g = *private_head;
489 if (unlikely(g == GNTTAB_LIST_END))
490 return -ENOSPC;
491 *private_head = gnttab_entry(g);
492 return g;
493}
494EXPORT_SYMBOL_GPL(gnttab_claim_grant_reference);
495
496void gnttab_release_grant_reference(grant_ref_t *private_head,
497 grant_ref_t release)
498{
499 gnttab_entry(release) = *private_head;
500 *private_head = release;
501}
502EXPORT_SYMBOL_GPL(gnttab_release_grant_reference);
503
504void gnttab_request_free_callback(struct gnttab_free_callback *callback,
505 void (*fn)(void *), void *arg, u16 count)
506{
507 unsigned long flags;
508 spin_lock_irqsave(&gnttab_list_lock, flags);
509 if (callback->next)
510 goto out;
511 callback->fn = fn;
512 callback->arg = arg;
513 callback->count = count;
514 callback->next = gnttab_free_callback_list;
515 gnttab_free_callback_list = callback;
516 check_free_callbacks();
517out:
518 spin_unlock_irqrestore(&gnttab_list_lock, flags);
519}
520EXPORT_SYMBOL_GPL(gnttab_request_free_callback);
521
522void gnttab_cancel_free_callback(struct gnttab_free_callback *callback)
523{
524 struct gnttab_free_callback **pcb;
525 unsigned long flags;
526
527 spin_lock_irqsave(&gnttab_list_lock, flags);
528 for (pcb = &gnttab_free_callback_list; *pcb; pcb = &(*pcb)->next) {
529 if (*pcb == callback) {
530 *pcb = callback->next;
531 break;
532 }
533 }
534 spin_unlock_irqrestore(&gnttab_list_lock, flags);
535}
536EXPORT_SYMBOL_GPL(gnttab_cancel_free_callback);
537
538static int grow_gnttab_list(unsigned int more_frames)
539{
540 unsigned int new_nr_grant_frames, extra_entries, i;
bbc60c18 541 unsigned int nr_glist_frames, new_nr_glist_frames;
ad9a8612
JF
542
543 new_nr_grant_frames = nr_grant_frames + more_frames;
544 extra_entries = more_frames * GREFS_PER_GRANT_FRAME;
545
bbc60c18
MAEM
546 nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP;
547 new_nr_glist_frames =
548 (new_nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP;
549 for (i = nr_glist_frames; i < new_nr_glist_frames; i++) {
ad9a8612
JF
550 gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_ATOMIC);
551 if (!gnttab_list[i])
552 goto grow_nomem;
553 }
554
555
556 for (i = GREFS_PER_GRANT_FRAME * nr_grant_frames;
557 i < GREFS_PER_GRANT_FRAME * new_nr_grant_frames - 1; i++)
558 gnttab_entry(i) = i + 1;
559
560 gnttab_entry(i) = gnttab_free_head;
561 gnttab_free_head = GREFS_PER_GRANT_FRAME * nr_grant_frames;
562 gnttab_free_count += extra_entries;
563
564 nr_grant_frames = new_nr_grant_frames;
565
566 check_free_callbacks();
567
568 return 0;
569
570grow_nomem:
bbc60c18 571 for ( ; i >= nr_glist_frames; i--)
ad9a8612
JF
572 free_page((unsigned long) gnttab_list[i]);
573 return -ENOMEM;
574}
575
576static unsigned int __max_nr_grant_frames(void)
577{
578 struct gnttab_query_size query;
579 int rc;
580
581 query.dom = DOMID_SELF;
582
583 rc = HYPERVISOR_grant_table_op(GNTTABOP_query_size, &query, 1);
584 if ((rc < 0) || (query.status != GNTST_okay))
585 return 4; /* Legacy max supported number of frames */
586
587 return query.max_nr_frames;
588}
589
183d03cc 590unsigned int gnttab_max_grant_frames(void)
ad9a8612
JF
591{
592 unsigned int xen_max = __max_nr_grant_frames();
593
594 if (xen_max > boot_max_nr_grant_frames)
595 return boot_max_nr_grant_frames;
596 return xen_max;
597}
183d03cc 598EXPORT_SYMBOL_GPL(gnttab_max_grant_frames);
ad9a8612 599
289b777e 600int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
0930bba6
SS
601 struct gnttab_map_grant_ref *kmap_ops,
602 struct page **pages, unsigned int count)
289b777e
SS
603{
604 int i, ret;
605 pte_t *pte;
606 unsigned long mfn;
607
608 ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map_ops, count);
87f1d40a
JF
609 if (ret)
610 return ret;
289b777e 611
aab8f11a
DDG
612 if (xen_feature(XENFEAT_auto_translated_physmap))
613 return ret;
614
289b777e 615 for (i = 0; i < count; i++) {
dc4972a4
IC
616 /* Do not add to override if the map failed. */
617 if (map_ops[i].status)
618 continue;
619
cf8d9163
KRW
620 if (map_ops[i].flags & GNTMAP_contains_pte) {
621 pte = (pte_t *) (mfn_to_virt(PFN_DOWN(map_ops[i].host_addr)) +
289b777e 622 (map_ops[i].host_addr & ~PAGE_MASK));
cf8d9163
KRW
623 mfn = pte_mfn(*pte);
624 } else {
625 /* If you really wanted to do this:
626 * mfn = PFN_DOWN(map_ops[i].dev_bus_addr);
627 *
628 * The reason we do not implement it is b/c on the
629 * unmap path (gnttab_unmap_refs) we have no means of
630 * checking whether the page is !GNTMAP_contains_pte.
631 *
632 * That is without some extra data-structure to carry
633 * the struct page, bool clear_pte, and list_head next
634 * tuples and deal with allocation/delallocation, etc.
635 *
636 * The users of this API set the GNTMAP_contains_pte
637 * flag so lets just return not supported until it
638 * becomes neccessary to implement.
639 */
640 return -EOPNOTSUPP;
641 }
0930bba6 642 ret = m2p_add_override(mfn, pages[i], &kmap_ops[i]);
87f1d40a
JF
643 if (ret)
644 return ret;
289b777e
SS
645 }
646
647 return ret;
648}
649EXPORT_SYMBOL_GPL(gnttab_map_refs);
650
651int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
652 struct page **pages, unsigned int count)
653{
654 int i, ret;
655
656 ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, unmap_ops, count);
87f1d40a
JF
657 if (ret)
658 return ret;
659
aab8f11a
DDG
660 if (xen_feature(XENFEAT_auto_translated_physmap))
661 return ret;
662
87f1d40a 663 for (i = 0; i < count; i++) {
cf8d9163 664 ret = m2p_remove_override(pages[i], true /* clear the PTE */);
87f1d40a
JF
665 if (ret)
666 return ret;
667 }
289b777e
SS
668
669 return ret;
670}
671EXPORT_SYMBOL_GPL(gnttab_unmap_refs);
672
85ff6acb
AL
673static unsigned nr_status_frames(unsigned nr_grant_frames)
674{
675 return (nr_grant_frames * GREFS_PER_GRANT_FRAME + SPP - 1) / SPP;
676}
677
0f9f5a95
AL
678static int gnttab_map_frames_v1(unsigned long *frames, unsigned int nr_gframes)
679{
680 int rc;
681
682 rc = arch_gnttab_map_shared(frames, nr_gframes,
683 gnttab_max_grant_frames(),
684 &gnttab_shared.addr);
685 BUG_ON(rc);
686
687 return 0;
688}
689
690static void gnttab_unmap_frames_v1(void)
691{
85ff6acb
AL
692 arch_gnttab_unmap(gnttab_shared.addr, nr_grant_frames);
693}
694
695static int gnttab_map_frames_v2(unsigned long *frames, unsigned int nr_gframes)
696{
697 uint64_t *sframes;
698 unsigned int nr_sframes;
699 struct gnttab_get_status_frames getframes;
700 int rc;
701
702 nr_sframes = nr_status_frames(nr_gframes);
703
704 /* No need for kzalloc as it is initialized in following hypercall
705 * GNTTABOP_get_status_frames.
706 */
707 sframes = kmalloc(nr_sframes * sizeof(uint64_t), GFP_ATOMIC);
708 if (!sframes)
709 return -ENOMEM;
710
711 getframes.dom = DOMID_SELF;
712 getframes.nr_frames = nr_sframes;
713 set_xen_guest_handle(getframes.frame_list, sframes);
714
715 rc = HYPERVISOR_grant_table_op(GNTTABOP_get_status_frames,
716 &getframes, 1);
717 if (rc == -ENOSYS) {
718 kfree(sframes);
719 return -ENOSYS;
720 }
721
722 BUG_ON(rc || getframes.status);
723
724 rc = arch_gnttab_map_status(sframes, nr_sframes,
725 nr_status_frames(gnttab_max_grant_frames()),
726 &grstatus);
727 BUG_ON(rc);
728 kfree(sframes);
729
730 rc = arch_gnttab_map_shared(frames, nr_gframes,
731 gnttab_max_grant_frames(),
732 &gnttab_shared.addr);
733 BUG_ON(rc);
734
735 return 0;
736}
737
738static void gnttab_unmap_frames_v2(void)
739{
740 arch_gnttab_unmap(gnttab_shared.addr, nr_grant_frames);
741 arch_gnttab_unmap(grstatus, nr_status_frames(nr_grant_frames));
0f9f5a95
AL
742}
743
ad9a8612
JF
744static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
745{
746 struct gnttab_setup_table setup;
747 unsigned long *frames;
748 unsigned int nr_gframes = end_idx + 1;
749 int rc;
750
183d03cc
SS
751 if (xen_hvm_domain()) {
752 struct xen_add_to_physmap xatp;
753 unsigned int i = end_idx;
754 rc = 0;
755 /*
756 * Loop backwards, so that the first hypercall has the largest
757 * index, ensuring that the table will grow only once.
758 */
759 do {
760 xatp.domid = DOMID_SELF;
761 xatp.idx = i;
762 xatp.space = XENMAPSPACE_grant_table;
763 xatp.gpfn = (xen_hvm_resume_frames >> PAGE_SHIFT) + i;
764 rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp);
765 if (rc != 0) {
766 printk(KERN_WARNING
767 "grant table add_to_physmap failed, err=%d\n", rc);
768 break;
769 }
770 } while (i-- > start_idx);
771
772 return rc;
773 }
774
85ff6acb
AL
775 /* No need for kzalloc as it is initialized in following hypercall
776 * GNTTABOP_setup_table.
777 */
ad9a8612
JF
778 frames = kmalloc(nr_gframes * sizeof(unsigned long), GFP_ATOMIC);
779 if (!frames)
780 return -ENOMEM;
781
782 setup.dom = DOMID_SELF;
783 setup.nr_frames = nr_gframes;
87e27cf6 784 set_xen_guest_handle(setup.frame_list, frames);
ad9a8612
JF
785
786 rc = HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
787 if (rc == -ENOSYS) {
788 kfree(frames);
789 return -ENOSYS;
790 }
791
792 BUG_ON(rc || setup.status);
793
0f9f5a95 794 rc = gnttab_interface->map_frames(frames, nr_gframes);
ad9a8612
JF
795
796 kfree(frames);
797
0f9f5a95
AL
798 return rc;
799}
800
801static struct gnttab_ops gnttab_v1_ops = {
802 .map_frames = gnttab_map_frames_v1,
803 .unmap_frames = gnttab_unmap_frames_v1,
804 .update_entry = gnttab_update_entry_v1,
805 .end_foreign_access_ref = gnttab_end_foreign_access_ref_v1,
806 .end_foreign_transfer_ref = gnttab_end_foreign_transfer_ref_v1,
807 .query_foreign_access = gnttab_query_foreign_access_v1,
808};
809
85ff6acb
AL
810static struct gnttab_ops gnttab_v2_ops = {
811 .map_frames = gnttab_map_frames_v2,
812 .unmap_frames = gnttab_unmap_frames_v2,
813 .update_entry = gnttab_update_entry_v2,
814 .end_foreign_access_ref = gnttab_end_foreign_access_ref_v2,
815 .end_foreign_transfer_ref = gnttab_end_foreign_transfer_ref_v2,
816 .query_foreign_access = gnttab_query_foreign_access_v2,
817};
818
0f9f5a95
AL
819static void gnttab_request_version(void)
820{
85ff6acb
AL
821 int rc;
822 struct gnttab_set_version gsv;
823
824 gsv.version = 2;
825 rc = HYPERVISOR_grant_table_op(GNTTABOP_set_version, &gsv, 1);
826 if (rc == 0) {
827 grant_table_version = 2;
828 gnttab_interface = &gnttab_v2_ops;
829 } else if (grant_table_version == 2) {
830 /*
831 * If we've already used version 2 features,
832 * but then suddenly discover that they're not
833 * available (e.g. migrating to an older
834 * version of Xen), almost unbounded badness
835 * can happen.
836 */
837 panic("we need grant tables version 2, but only version 1 is available");
838 } else {
839 grant_table_version = 1;
840 gnttab_interface = &gnttab_v1_ops;
841 }
0f9f5a95
AL
842 printk(KERN_INFO "Grant tables using version %d layout.\n",
843 grant_table_version);
ad9a8612
JF
844}
845
0e91398f 846int gnttab_resume(void)
ad9a8612 847{
183d03cc
SS
848 unsigned int max_nr_gframes;
849
0f9f5a95 850 gnttab_request_version();
183d03cc
SS
851 max_nr_gframes = gnttab_max_grant_frames();
852 if (max_nr_gframes < nr_grant_frames)
ad9a8612 853 return -ENOSYS;
183d03cc
SS
854
855 if (xen_pv_domain())
856 return gnttab_map(0, nr_grant_frames - 1);
857
0f9f5a95
AL
858 if (gnttab_shared.addr == NULL) {
859 gnttab_shared.addr = ioremap(xen_hvm_resume_frames,
860 PAGE_SIZE * max_nr_gframes);
861 if (gnttab_shared.addr == NULL) {
183d03cc
SS
862 printk(KERN_WARNING
863 "Failed to ioremap gnttab share frames!");
864 return -ENOMEM;
865 }
866 }
867
868 gnttab_map(0, nr_grant_frames - 1);
869
870 return 0;
ad9a8612
JF
871}
872
0e91398f 873int gnttab_suspend(void)
ad9a8612 874{
0f9f5a95 875 gnttab_interface->unmap_frames();
ad9a8612
JF
876 return 0;
877}
878
879static int gnttab_expand(unsigned int req_entries)
880{
881 int rc;
882 unsigned int cur, extra;
883
884 cur = nr_grant_frames;
885 extra = ((req_entries + (GREFS_PER_GRANT_FRAME-1)) /
886 GREFS_PER_GRANT_FRAME);
183d03cc 887 if (cur + extra > gnttab_max_grant_frames())
ad9a8612
JF
888 return -ENOSPC;
889
890 rc = gnttab_map(cur, cur + extra - 1);
891 if (rc == 0)
892 rc = grow_gnttab_list(extra);
893
894 return rc;
895}
896
183d03cc 897int gnttab_init(void)
ad9a8612
JF
898{
899 int i;
bbc60c18 900 unsigned int max_nr_glist_frames, nr_glist_frames;
ad9a8612
JF
901 unsigned int nr_init_grefs;
902
ad9a8612
JF
903 nr_grant_frames = 1;
904 boot_max_nr_grant_frames = __max_nr_grant_frames();
905
906 /* Determine the maximum number of frames required for the
907 * grant reference free list on the current hypervisor.
908 */
909 max_nr_glist_frames = (boot_max_nr_grant_frames *
bbc60c18 910 GREFS_PER_GRANT_FRAME / RPP);
ad9a8612
JF
911
912 gnttab_list = kmalloc(max_nr_glist_frames * sizeof(grant_ref_t *),
913 GFP_KERNEL);
914 if (gnttab_list == NULL)
915 return -ENOMEM;
916
bbc60c18
MAEM
917 nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP;
918 for (i = 0; i < nr_glist_frames; i++) {
ad9a8612
JF
919 gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_KERNEL);
920 if (gnttab_list[i] == NULL)
921 goto ini_nomem;
922 }
923
924 if (gnttab_resume() < 0)
925 return -ENODEV;
926
927 nr_init_grefs = nr_grant_frames * GREFS_PER_GRANT_FRAME;
928
929 for (i = NR_RESERVED_ENTRIES; i < nr_init_grefs - 1; i++)
930 gnttab_entry(i) = i + 1;
931
932 gnttab_entry(nr_init_grefs - 1) = GNTTAB_LIST_END;
933 gnttab_free_count = nr_init_grefs - NR_RESERVED_ENTRIES;
934 gnttab_free_head = NR_RESERVED_ENTRIES;
935
936 printk("Grant table initialized\n");
937 return 0;
938
939 ini_nomem:
940 for (i--; i >= 0; i--)
941 free_page((unsigned long)gnttab_list[i]);
942 kfree(gnttab_list);
943 return -ENOMEM;
944}
183d03cc
SS
945EXPORT_SYMBOL_GPL(gnttab_init);
946
947static int __devinit __gnttab_init(void)
948{
949 /* Delay grant-table initialization in the PV on HVM case */
950 if (xen_hvm_domain())
951 return 0;
952
953 if (!xen_pv_domain())
954 return -ENODEV;
955
956 return gnttab_init();
957}
ad9a8612 958
183d03cc 959core_initcall(__gnttab_init);