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