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