Linux Audio

Check our new training course

Linux debugging, profiling, tracing and performance analysis training

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