summaryrefslogtreecommitdiffstats
path: root/drivers/xen/grant-table.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-01-10 13:09:59 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-01-10 13:09:59 -0500
commit90160371b3a3e67ef78d68210a94dd30664a703d (patch)
tree2841ea811be129133cf9b83d9c3badd96e7ffab4 /drivers/xen/grant-table.c
parentae5cfc0546ca2698b9dcddf72accbd70e57590a0 (diff)
parent6c254de16a1d14c1ac931d3aa08dc88ac9fc582b (diff)
Merge branch 'stable/for-linus-3.3' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen
* 'stable/for-linus-3.3' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen: (37 commits) xen/pciback: Expand the warning message to include domain id. xen/pciback: Fix "device has been assigned to X domain!" warning xen/pciback: Move the PCI_DEV_FLAGS_ASSIGNED ops to the "[un|]bind" xen/xenbus: don't reimplement kvasprintf via a fixed size buffer xenbus: maximum buffer size is XENSTORE_PAYLOAD_MAX xen/xenbus: Reject replies with payload > XENSTORE_PAYLOAD_MAX. Xen: consolidate and simplify struct xenbus_driver instantiation xen-gntalloc: introduce missing kfree xen/xenbus: Fix compile error - missing header for xen_initial_domain() xen/netback: Enable netback on HVM guests xen/grant-table: Support mappings required by blkback xenbus: Use grant-table wrapper functions xenbus: Support HVM backends xen/xenbus-frontend: Fix compile error with randconfig xen/xenbus-frontend: Make error message more clear xen/privcmd: Remove unused support for arch specific privcmp mmap xen: Add xenbus_backend device xen: Add xenbus device driver xen: Add privcmd device driver xen/gntalloc: fix reference counts on multi-page mappings ...
Diffstat (limited to 'drivers/xen/grant-table.c')
-rw-r--r--drivers/xen/grant-table.c518
1 files changed, 457 insertions, 61 deletions
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
index bf1c094f4ebf..1cd94daa71db 100644
--- a/drivers/xen/grant-table.c
+++ b/drivers/xen/grant-table.c
@@ -44,16 +44,19 @@
44#include <xen/page.h> 44#include <xen/page.h>
45#include <xen/grant_table.h> 45#include <xen/grant_table.h>
46#include <xen/interface/memory.h> 46#include <xen/interface/memory.h>
47#include <xen/hvc-console.h>
47#include <asm/xen/hypercall.h> 48#include <asm/xen/hypercall.h>
48 49
49#include <asm/pgtable.h> 50#include <asm/pgtable.h>
50#include <asm/sync_bitops.h> 51#include <asm/sync_bitops.h>
51 52
52
53/* External tools reserve first few grant table entries. */ 53/* External tools reserve first few grant table entries. */
54#define NR_RESERVED_ENTRIES 8 54#define NR_RESERVED_ENTRIES 8
55#define GNTTAB_LIST_END 0xffffffff 55#define GNTTAB_LIST_END 0xffffffff
56#define GREFS_PER_GRANT_FRAME (PAGE_SIZE / sizeof(struct grant_entry)) 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)))
57 60
58static grant_ref_t **gnttab_list; 61static grant_ref_t **gnttab_list;
59static unsigned int nr_grant_frames; 62static unsigned int nr_grant_frames;
@@ -64,13 +67,97 @@ static DEFINE_SPINLOCK(gnttab_list_lock);
64unsigned long xen_hvm_resume_frames; 67unsigned long xen_hvm_resume_frames;
65EXPORT_SYMBOL_GPL(xen_hvm_resume_frames); 68EXPORT_SYMBOL_GPL(xen_hvm_resume_frames);
66 69
67static struct grant_entry *shared; 70static union {
71 struct grant_entry_v1 *v1;
72 union grant_entry_v2 *v2;
73 void *addr;
74} gnttab_shared;
75
76/*This is a structure of function pointers for grant table*/
77struct gnttab_ops {
78 /*
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.
83 */
84 int (*map_frames)(unsigned long *frames, unsigned int nr_gframes);
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 /*
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.
96 */
97 void (*update_entry)(grant_ref_t ref, domid_t domid,
98 unsigned long frame, unsigned flags);
99 /*
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
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 */
107 int (*end_foreign_access_ref)(grant_ref_t ref, int readonly);
108 /*
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.
114 */
115 unsigned long (*end_foreign_transfer_ref)(grant_ref_t ref);
116 /*
117 * Query the status of a grant entry. Ref parameter is reference of
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 */
122 int (*query_foreign_access)(grant_ref_t ref);
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);
134 /*
135 * Redirect an available grant entry on domain A to another grant
136 * reference of domain B, then allow domain C to use grant reference
137 * of domain B transitively. Ref parameter is an available grant entry
138 * reference on domain A, domid is id of domain C which accesses grant
139 * entry transitively, flags is grant type and flag information,
140 * trans_domid is id of domain B whose grant entry is finally accessed
141 * transitively, trans_gref is grant entry transitive reference of
142 * domain B.
143 */
144 void (*update_trans_entry)(grant_ref_t ref, domid_t domid, int flags,
145 domid_t trans_domid, grant_ref_t trans_gref);
146};
147
148static struct gnttab_ops *gnttab_interface;
149
150/*This reflects status of grant entries, so act as a global value*/
151static grant_status_t *grstatus;
152
153static int grant_table_version;
68 154
69static struct gnttab_free_callback *gnttab_free_callback_list; 155static struct gnttab_free_callback *gnttab_free_callback_list;
70 156
71static int gnttab_expand(unsigned int req_entries); 157static int gnttab_expand(unsigned int req_entries);
72 158
73#define RPP (PAGE_SIZE / sizeof(grant_ref_t)) 159#define RPP (PAGE_SIZE / sizeof(grant_ref_t))
160#define SPP (PAGE_SIZE / sizeof(grant_status_t))
74 161
75static inline grant_ref_t *__gnttab_entry(grant_ref_t entry) 162static inline grant_ref_t *__gnttab_entry(grant_ref_t entry)
76{ 163{
@@ -142,23 +229,33 @@ static void put_free_entry(grant_ref_t ref)
142 spin_unlock_irqrestore(&gnttab_list_lock, flags); 229 spin_unlock_irqrestore(&gnttab_list_lock, flags);
143} 230}
144 231
145static void update_grant_entry(grant_ref_t ref, domid_t domid, 232/*
146 unsigned long frame, unsigned flags) 233 * Following applies to gnttab_update_entry_v1 and gnttab_update_entry_v2.
234 * Introducing a valid entry into the grant table:
235 * 1. Write ent->domid.
236 * 2. Write ent->frame:
237 * GTF_permit_access: Frame to which access is permitted.
238 * GTF_accept_transfer: Pseudo-phys frame slot being filled by new
239 * frame, or zero if none.
240 * 3. Write memory barrier (WMB).
241 * 4. Write ent->flags, inc. valid type.
242 */
243static void gnttab_update_entry_v1(grant_ref_t ref, domid_t domid,
244 unsigned long frame, unsigned flags)
245{
246 gnttab_shared.v1[ref].domid = domid;
247 gnttab_shared.v1[ref].frame = frame;
248 wmb();
249 gnttab_shared.v1[ref].flags = flags;
250}
251
252static void gnttab_update_entry_v2(grant_ref_t ref, domid_t domid,
253 unsigned long frame, unsigned flags)
147{ 254{
148 /* 255 gnttab_shared.v2[ref].hdr.domid = domid;
149 * Introducing a valid entry into the grant table: 256 gnttab_shared.v2[ref].full_page.frame = frame;
150 * 1. Write ent->domid.
151 * 2. Write ent->frame:
152 * GTF_permit_access: Frame to which access is permitted.
153 * GTF_accept_transfer: Pseudo-phys frame slot being filled by new
154 * frame, or zero if none.
155 * 3. Write memory barrier (WMB).
156 * 4. Write ent->flags, inc. valid type.
157 */
158 shared[ref].frame = frame;
159 shared[ref].domid = domid;
160 wmb(); 257 wmb();
161 shared[ref].flags = flags; 258 gnttab_shared.v2[ref].hdr.flags = GTF_permit_access | flags;
162} 259}
163 260
164/* 261/*
@@ -167,7 +264,7 @@ static void update_grant_entry(grant_ref_t ref, domid_t domid,
167void gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid, 264void gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid,
168 unsigned long frame, int readonly) 265 unsigned long frame, int readonly)
169{ 266{
170 update_grant_entry(ref, domid, frame, 267 gnttab_interface->update_entry(ref, domid, frame,
171 GTF_permit_access | (readonly ? GTF_readonly : 0)); 268 GTF_permit_access | (readonly ? GTF_readonly : 0));
172} 269}
173EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access_ref); 270EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access_ref);
@@ -187,31 +284,184 @@ int gnttab_grant_foreign_access(domid_t domid, unsigned long frame,
187} 284}
188EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access); 285EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access);
189 286
190int gnttab_query_foreign_access(grant_ref_t ref) 287void gnttab_update_subpage_entry_v2(grant_ref_t ref, domid_t domid,
288 unsigned long frame, int flags,
289 unsigned page_off,
290 unsigned length)
291{
292 gnttab_shared.v2[ref].sub_page.frame = frame;
293 gnttab_shared.v2[ref].sub_page.page_off = page_off;
294 gnttab_shared.v2[ref].sub_page.length = length;
295 gnttab_shared.v2[ref].hdr.domid = domid;
296 wmb();
297 gnttab_shared.v2[ref].hdr.flags =
298 GTF_permit_access | GTF_sub_page | flags;
299}
300
301int gnttab_grant_foreign_access_subpage_ref(grant_ref_t ref, domid_t domid,
302 unsigned long frame, int flags,
303 unsigned page_off,
304 unsigned length)
191{ 305{
192 u16 nflags; 306 if (flags & (GTF_accept_transfer | GTF_reading |
307 GTF_writing | GTF_transitive))
308 return -EPERM;
193 309
194 nflags = shared[ref].flags; 310 if (gnttab_interface->update_subpage_entry == NULL)
311 return -ENOSYS;
195 312
196 return nflags & (GTF_reading|GTF_writing); 313 gnttab_interface->update_subpage_entry(ref, domid, frame, flags,
314 page_off, length);
315
316 return 0;
317}
318EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access_subpage_ref);
319
320int gnttab_grant_foreign_access_subpage(domid_t domid, unsigned long frame,
321 int flags, unsigned page_off,
322 unsigned length)
323{
324 int ref, rc;
325
326 ref = get_free_entries(1);
327 if (unlikely(ref < 0))
328 return -ENOSPC;
329
330 rc = gnttab_grant_foreign_access_subpage_ref(ref, domid, frame, flags,
331 page_off, length);
332 if (rc < 0) {
333 put_free_entry(ref);
334 return rc;
335 }
336
337 return ref;
338}
339EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access_subpage);
340
341bool gnttab_subpage_grants_available(void)
342{
343 return gnttab_interface->update_subpage_entry != NULL;
344}
345EXPORT_SYMBOL_GPL(gnttab_subpage_grants_available);
346
347void gnttab_update_trans_entry_v2(grant_ref_t ref, domid_t domid,
348 int flags, domid_t trans_domid,
349 grant_ref_t trans_gref)
350{
351 gnttab_shared.v2[ref].transitive.trans_domid = trans_domid;
352 gnttab_shared.v2[ref].transitive.gref = trans_gref;
353 gnttab_shared.v2[ref].hdr.domid = domid;
354 wmb();
355 gnttab_shared.v2[ref].hdr.flags =
356 GTF_permit_access | GTF_transitive | flags;
357}
358
359int gnttab_grant_foreign_access_trans_ref(grant_ref_t ref, domid_t domid,
360 int flags, domid_t trans_domid,
361 grant_ref_t trans_gref)
362{
363 if (flags & (GTF_accept_transfer | GTF_reading |
364 GTF_writing | GTF_sub_page))
365 return -EPERM;
366
367 if (gnttab_interface->update_trans_entry == NULL)
368 return -ENOSYS;
369
370 gnttab_interface->update_trans_entry(ref, domid, flags, trans_domid,
371 trans_gref);
372
373 return 0;
374}
375EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access_trans_ref);
376
377int gnttab_grant_foreign_access_trans(domid_t domid, int flags,
378 domid_t trans_domid,
379 grant_ref_t trans_gref)
380{
381 int ref, rc;
382
383 ref = get_free_entries(1);
384 if (unlikely(ref < 0))
385 return -ENOSPC;
386
387 rc = gnttab_grant_foreign_access_trans_ref(ref, domid, flags,
388 trans_domid, trans_gref);
389 if (rc < 0) {
390 put_free_entry(ref);
391 return rc;
392 }
393
394 return ref;
395}
396EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access_trans);
397
398bool gnttab_trans_grants_available(void)
399{
400 return gnttab_interface->update_trans_entry != NULL;
401}
402EXPORT_SYMBOL_GPL(gnttab_trans_grants_available);
403
404static int gnttab_query_foreign_access_v1(grant_ref_t ref)
405{
406 return gnttab_shared.v1[ref].flags & (GTF_reading|GTF_writing);
407}
408
409static int gnttab_query_foreign_access_v2(grant_ref_t ref)
410{
411 return grstatus[ref] & (GTF_reading|GTF_writing);
412}
413
414int gnttab_query_foreign_access(grant_ref_t ref)
415{
416 return gnttab_interface->query_foreign_access(ref);
197} 417}
198EXPORT_SYMBOL_GPL(gnttab_query_foreign_access); 418EXPORT_SYMBOL_GPL(gnttab_query_foreign_access);
199 419
200int gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly) 420static int gnttab_end_foreign_access_ref_v1(grant_ref_t ref, int readonly)
201{ 421{
202 u16 flags, nflags; 422 u16 flags, nflags;
423 u16 *pflags;
203 424
204 nflags = shared[ref].flags; 425 pflags = &gnttab_shared.v1[ref].flags;
426 nflags = *pflags;
205 do { 427 do {
206 flags = nflags; 428 flags = nflags;
207 if (flags & (GTF_reading|GTF_writing)) { 429 if (flags & (GTF_reading|GTF_writing)) {
208 printk(KERN_ALERT "WARNING: g.e. still in use!\n"); 430 printk(KERN_ALERT "WARNING: g.e. still in use!\n");
209 return 0; 431 return 0;
210 } 432 }
211 } while ((nflags = sync_cmpxchg(&shared[ref].flags, flags, 0)) != flags); 433 } while ((nflags = sync_cmpxchg(pflags, flags, 0)) != flags);
434
435 return 1;
436}
437
438static int gnttab_end_foreign_access_ref_v2(grant_ref_t ref, int readonly)
439{
440 gnttab_shared.v2[ref].hdr.flags = 0;
441 mb();
442 if (grstatus[ref] & (GTF_reading|GTF_writing)) {
443 return 0;
444 } else {
445 /* The read of grstatus needs to have acquire
446 semantics. On x86, reads already have
447 that, and we just need to protect against
448 compiler reorderings. On other
449 architectures we may need a full
450 barrier. */
451#ifdef CONFIG_X86
452 barrier();
453#else
454 mb();
455#endif
456 }
212 457
213 return 1; 458 return 1;
214} 459}
460
461int gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly)
462{
463 return gnttab_interface->end_foreign_access_ref(ref, readonly);
464}
215EXPORT_SYMBOL_GPL(gnttab_end_foreign_access_ref); 465EXPORT_SYMBOL_GPL(gnttab_end_foreign_access_ref);
216 466
217void gnttab_end_foreign_access(grant_ref_t ref, int readonly, 467void gnttab_end_foreign_access(grant_ref_t ref, int readonly,
@@ -246,37 +496,76 @@ EXPORT_SYMBOL_GPL(gnttab_grant_foreign_transfer);
246void gnttab_grant_foreign_transfer_ref(grant_ref_t ref, domid_t domid, 496void gnttab_grant_foreign_transfer_ref(grant_ref_t ref, domid_t domid,
247 unsigned long pfn) 497 unsigned long pfn)
248{ 498{
249 update_grant_entry(ref, domid, pfn, GTF_accept_transfer); 499 gnttab_interface->update_entry(ref, domid, pfn, GTF_accept_transfer);
250} 500}
251EXPORT_SYMBOL_GPL(gnttab_grant_foreign_transfer_ref); 501EXPORT_SYMBOL_GPL(gnttab_grant_foreign_transfer_ref);
252 502
253unsigned long gnttab_end_foreign_transfer_ref(grant_ref_t ref) 503static unsigned long gnttab_end_foreign_transfer_ref_v1(grant_ref_t ref)
254{ 504{
255 unsigned long frame; 505 unsigned long frame;
256 u16 flags; 506 u16 flags;
507 u16 *pflags;
508
509 pflags = &gnttab_shared.v1[ref].flags;
257 510
258 /* 511 /*
259 * If a transfer is not even yet started, try to reclaim the grant 512 * If a transfer is not even yet started, try to reclaim the grant
260 * reference and return failure (== 0). 513 * reference and return failure (== 0).
261 */ 514 */
262 while (!((flags = shared[ref].flags) & GTF_transfer_committed)) { 515 while (!((flags = *pflags) & GTF_transfer_committed)) {
263 if (sync_cmpxchg(&shared[ref].flags, flags, 0) == flags) 516 if (sync_cmpxchg(pflags, flags, 0) == flags)
264 return 0; 517 return 0;
265 cpu_relax(); 518 cpu_relax();
266 } 519 }
267 520
268 /* If a transfer is in progress then wait until it is completed. */ 521 /* If a transfer is in progress then wait until it is completed. */
269 while (!(flags & GTF_transfer_completed)) { 522 while (!(flags & GTF_transfer_completed)) {
270 flags = shared[ref].flags; 523 flags = *pflags;
271 cpu_relax(); 524 cpu_relax();
272 } 525 }
273 526
274 rmb(); /* Read the frame number /after/ reading completion status. */ 527 rmb(); /* Read the frame number /after/ reading completion status. */
275 frame = shared[ref].frame; 528 frame = gnttab_shared.v1[ref].frame;
529 BUG_ON(frame == 0);
530
531 return frame;
532}
533
534static unsigned long gnttab_end_foreign_transfer_ref_v2(grant_ref_t ref)
535{
536 unsigned long frame;
537 u16 flags;
538 u16 *pflags;
539
540 pflags = &gnttab_shared.v2[ref].hdr.flags;
541
542 /*
543 * If a transfer is not even yet started, try to reclaim the grant
544 * reference and return failure (== 0).
545 */
546 while (!((flags = *pflags) & GTF_transfer_committed)) {
547 if (sync_cmpxchg(pflags, flags, 0) == flags)
548 return 0;
549 cpu_relax();
550 }
551
552 /* If a transfer is in progress then wait until it is completed. */
553 while (!(flags & GTF_transfer_completed)) {
554 flags = *pflags;
555 cpu_relax();
556 }
557
558 rmb(); /* Read the frame number /after/ reading completion status. */
559 frame = gnttab_shared.v2[ref].full_page.frame;
276 BUG_ON(frame == 0); 560 BUG_ON(frame == 0);
277 561
278 return frame; 562 return frame;
279} 563}
564
565unsigned long gnttab_end_foreign_transfer_ref(grant_ref_t ref)
566{
567 return gnttab_interface->end_foreign_transfer_ref(ref);
568}
280EXPORT_SYMBOL_GPL(gnttab_end_foreign_transfer_ref); 569EXPORT_SYMBOL_GPL(gnttab_end_foreign_transfer_ref);
281 570
282unsigned long gnttab_end_foreign_transfer(grant_ref_t ref) 571unsigned long gnttab_end_foreign_transfer(grant_ref_t ref)
@@ -448,8 +737,8 @@ unsigned int gnttab_max_grant_frames(void)
448EXPORT_SYMBOL_GPL(gnttab_max_grant_frames); 737EXPORT_SYMBOL_GPL(gnttab_max_grant_frames);
449 738
450int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops, 739int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
451 struct gnttab_map_grant_ref *kmap_ops, 740 struct gnttab_map_grant_ref *kmap_ops,
452 struct page **pages, unsigned int count) 741 struct page **pages, unsigned int count)
453{ 742{
454 int i, ret; 743 int i, ret;
455 pte_t *pte; 744 pte_t *pte;
@@ -472,24 +761,10 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
472 (map_ops[i].host_addr & ~PAGE_MASK)); 761 (map_ops[i].host_addr & ~PAGE_MASK));
473 mfn = pte_mfn(*pte); 762 mfn = pte_mfn(*pte);
474 } else { 763 } else {
475 /* If you really wanted to do this: 764 mfn = PFN_DOWN(map_ops[i].dev_bus_addr);
476 * mfn = PFN_DOWN(map_ops[i].dev_bus_addr);
477 *
478 * The reason we do not implement it is b/c on the
479 * unmap path (gnttab_unmap_refs) we have no means of
480 * checking whether the page is !GNTMAP_contains_pte.
481 *
482 * That is without some extra data-structure to carry
483 * the struct page, bool clear_pte, and list_head next
484 * tuples and deal with allocation/delallocation, etc.
485 *
486 * The users of this API set the GNTMAP_contains_pte
487 * flag so lets just return not supported until it
488 * becomes neccessary to implement.
489 */
490 return -EOPNOTSUPP;
491 } 765 }
492 ret = m2p_add_override(mfn, pages[i], &kmap_ops[i]); 766 ret = m2p_add_override(mfn, pages[i], kmap_ops ?
767 &kmap_ops[i] : NULL);
493 if (ret) 768 if (ret)
494 return ret; 769 return ret;
495 } 770 }
@@ -499,7 +774,7 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
499EXPORT_SYMBOL_GPL(gnttab_map_refs); 774EXPORT_SYMBOL_GPL(gnttab_map_refs);
500 775
501int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops, 776int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
502 struct page **pages, unsigned int count) 777 struct page **pages, unsigned int count, bool clear_pte)
503{ 778{
504 int i, ret; 779 int i, ret;
505 780
@@ -511,7 +786,7 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
511 return ret; 786 return ret;
512 787
513 for (i = 0; i < count; i++) { 788 for (i = 0; i < count; i++) {
514 ret = m2p_remove_override(pages[i], true /* clear the PTE */); 789 ret = m2p_remove_override(pages[i], clear_pte);
515 if (ret) 790 if (ret)
516 return ret; 791 return ret;
517 } 792 }
@@ -520,6 +795,77 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
520} 795}
521EXPORT_SYMBOL_GPL(gnttab_unmap_refs); 796EXPORT_SYMBOL_GPL(gnttab_unmap_refs);
522 797
798static unsigned nr_status_frames(unsigned nr_grant_frames)
799{
800 return (nr_grant_frames * GREFS_PER_GRANT_FRAME + SPP - 1) / SPP;
801}
802
803static int gnttab_map_frames_v1(unsigned long *frames, unsigned int nr_gframes)
804{
805 int rc;
806
807 rc = arch_gnttab_map_shared(frames, nr_gframes,
808 gnttab_max_grant_frames(),
809 &gnttab_shared.addr);
810 BUG_ON(rc);
811
812 return 0;
813}
814
815static void gnttab_unmap_frames_v1(void)
816{
817 arch_gnttab_unmap(gnttab_shared.addr, nr_grant_frames);
818}
819
820static int gnttab_map_frames_v2(unsigned long *frames, unsigned int nr_gframes)
821{
822 uint64_t *sframes;
823 unsigned int nr_sframes;
824 struct gnttab_get_status_frames getframes;
825 int rc;
826
827 nr_sframes = nr_status_frames(nr_gframes);
828
829 /* No need for kzalloc as it is initialized in following hypercall
830 * GNTTABOP_get_status_frames.
831 */
832 sframes = kmalloc(nr_sframes * sizeof(uint64_t), GFP_ATOMIC);
833 if (!sframes)
834 return -ENOMEM;
835
836 getframes.dom = DOMID_SELF;
837 getframes.nr_frames = nr_sframes;
838 set_xen_guest_handle(getframes.frame_list, sframes);
839
840 rc = HYPERVISOR_grant_table_op(GNTTABOP_get_status_frames,
841 &getframes, 1);
842 if (rc == -ENOSYS) {
843 kfree(sframes);
844 return -ENOSYS;
845 }
846
847 BUG_ON(rc || getframes.status);
848
849 rc = arch_gnttab_map_status(sframes, nr_sframes,
850 nr_status_frames(gnttab_max_grant_frames()),
851 &grstatus);
852 BUG_ON(rc);
853 kfree(sframes);
854
855 rc = arch_gnttab_map_shared(frames, nr_gframes,
856 gnttab_max_grant_frames(),
857 &gnttab_shared.addr);
858 BUG_ON(rc);
859
860 return 0;
861}
862
863static void gnttab_unmap_frames_v2(void)
864{
865 arch_gnttab_unmap(gnttab_shared.addr, nr_grant_frames);
866 arch_gnttab_unmap(grstatus, nr_status_frames(nr_grant_frames));
867}
868
523static int gnttab_map(unsigned int start_idx, unsigned int end_idx) 869static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
524{ 870{
525 struct gnttab_setup_table setup; 871 struct gnttab_setup_table setup;
@@ -551,6 +897,9 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
551 return rc; 897 return rc;
552 } 898 }
553 899
900 /* No need for kzalloc as it is initialized in following hypercall
901 * GNTTABOP_setup_table.
902 */
554 frames = kmalloc(nr_gframes * sizeof(unsigned long), GFP_ATOMIC); 903 frames = kmalloc(nr_gframes * sizeof(unsigned long), GFP_ATOMIC);
555 if (!frames) 904 if (!frames)
556 return -ENOMEM; 905 return -ENOMEM;
@@ -567,19 +916,65 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
567 916
568 BUG_ON(rc || setup.status); 917 BUG_ON(rc || setup.status);
569 918
570 rc = arch_gnttab_map_shared(frames, nr_gframes, gnttab_max_grant_frames(), 919 rc = gnttab_interface->map_frames(frames, nr_gframes);
571 &shared);
572 BUG_ON(rc);
573 920
574 kfree(frames); 921 kfree(frames);
575 922
576 return 0; 923 return rc;
924}
925
926static struct gnttab_ops gnttab_v1_ops = {
927 .map_frames = gnttab_map_frames_v1,
928 .unmap_frames = gnttab_unmap_frames_v1,
929 .update_entry = gnttab_update_entry_v1,
930 .end_foreign_access_ref = gnttab_end_foreign_access_ref_v1,
931 .end_foreign_transfer_ref = gnttab_end_foreign_transfer_ref_v1,
932 .query_foreign_access = gnttab_query_foreign_access_v1,
933};
934
935static struct gnttab_ops gnttab_v2_ops = {
936 .map_frames = gnttab_map_frames_v2,
937 .unmap_frames = gnttab_unmap_frames_v2,
938 .update_entry = gnttab_update_entry_v2,
939 .end_foreign_access_ref = gnttab_end_foreign_access_ref_v2,
940 .end_foreign_transfer_ref = gnttab_end_foreign_transfer_ref_v2,
941 .query_foreign_access = gnttab_query_foreign_access_v2,
942 .update_subpage_entry = gnttab_update_subpage_entry_v2,
943 .update_trans_entry = gnttab_update_trans_entry_v2,
944};
945
946static void gnttab_request_version(void)
947{
948 int rc;
949 struct gnttab_set_version gsv;
950
951 gsv.version = 2;
952 rc = HYPERVISOR_grant_table_op(GNTTABOP_set_version, &gsv, 1);
953 if (rc == 0) {
954 grant_table_version = 2;
955 gnttab_interface = &gnttab_v2_ops;
956 } else if (grant_table_version == 2) {
957 /*
958 * If we've already used version 2 features,
959 * but then suddenly discover that they're not
960 * available (e.g. migrating to an older
961 * version of Xen), almost unbounded badness
962 * can happen.
963 */
964 panic("we need grant tables version 2, but only version 1 is available");
965 } else {
966 grant_table_version = 1;
967 gnttab_interface = &gnttab_v1_ops;
968 }
969 printk(KERN_INFO "Grant tables using version %d layout.\n",
970 grant_table_version);
577} 971}
578 972
579int gnttab_resume(void) 973int gnttab_resume(void)
580{ 974{
581 unsigned int max_nr_gframes; 975 unsigned int max_nr_gframes;
582 976
977 gnttab_request_version();
583 max_nr_gframes = gnttab_max_grant_frames(); 978 max_nr_gframes = gnttab_max_grant_frames();
584 if (max_nr_gframes < nr_grant_frames) 979 if (max_nr_gframes < nr_grant_frames)
585 return -ENOSYS; 980 return -ENOSYS;
@@ -587,9 +982,10 @@ int gnttab_resume(void)
587 if (xen_pv_domain()) 982 if (xen_pv_domain())
588 return gnttab_map(0, nr_grant_frames - 1); 983 return gnttab_map(0, nr_grant_frames - 1);
589 984
590 if (!shared) { 985 if (gnttab_shared.addr == NULL) {
591 shared = ioremap(xen_hvm_resume_frames, PAGE_SIZE * max_nr_gframes); 986 gnttab_shared.addr = ioremap(xen_hvm_resume_frames,
592 if (shared == NULL) { 987 PAGE_SIZE * max_nr_gframes);
988 if (gnttab_shared.addr == NULL) {
593 printk(KERN_WARNING 989 printk(KERN_WARNING
594 "Failed to ioremap gnttab share frames!"); 990 "Failed to ioremap gnttab share frames!");
595 return -ENOMEM; 991 return -ENOMEM;
@@ -603,7 +999,7 @@ int gnttab_resume(void)
603 999
604int gnttab_suspend(void) 1000int gnttab_suspend(void)
605{ 1001{
606 arch_gnttab_unmap_shared(shared, nr_grant_frames); 1002 gnttab_interface->unmap_frames();
607 return 0; 1003 return 0;
608} 1004}
609 1005