- Update Xen patches to 3.3-rc5 and c/s 1157.
[linux-flexiantxendom0-3.2.10.git] / drivers / xen / core / gnttab.c
1 /******************************************************************************
2  * gnttab.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/export.h>
35 #include <linux/slab.h>
36 #include <linux/sched.h>
37 #include <linux/mm.h>
38 #include <linux/seqlock.h>
39 #include <xen/interface/xen.h>
40 #include <xen/gnttab.h>
41 #include <asm/pgtable.h>
42 #include <asm/uaccess.h>
43 #include <asm/cmpxchg.h>
44 #include <asm/io.h>
45 #include <xen/interface/memory.h>
46 #include <asm/gnttab_dma.h>
47
48 #ifdef HAVE_XEN_PLATFORM_COMPAT_H
49 #include <xen/platform-compat.h>
50 #endif
51
52 /* External tools reserve first few grant table entries. */
53 #define NR_RESERVED_ENTRIES 8
54 #define GNTTAB_LIST_END 0xffffffff
55 #define ENTRIES_PER_GRANT_FRAME (PAGE_SIZE / sizeof(grant_entry_t))
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
64 static struct grant_entry *shared;
65
66 static struct gnttab_free_callback *gnttab_free_callback_list;
67
68 static int gnttab_expand(unsigned int req_entries);
69
70 #define RPP (PAGE_SIZE / sizeof(grant_ref_t))
71 #define gnttab_entry(entry) (gnttab_list[(entry) / RPP][(entry) % RPP])
72
73 #define nr_freelist_frames(grant_frames)                                \
74         (((grant_frames) * ENTRIES_PER_GRANT_FRAME + RPP - 1) / RPP)
75
76 static int get_free_entries(int count)
77 {
78         unsigned long flags;
79         int ref, rc;
80         grant_ref_t head;
81
82         spin_lock_irqsave(&gnttab_list_lock, flags);
83
84         if ((gnttab_free_count < count) &&
85             ((rc = gnttab_expand(count - gnttab_free_count)) < 0)) {
86                 spin_unlock_irqrestore(&gnttab_list_lock, flags);
87                 return rc;
88         }
89
90         ref = head = gnttab_free_head;
91         gnttab_free_count -= count;
92         while (count-- > 1)
93                 head = gnttab_entry(head);
94         gnttab_free_head = gnttab_entry(head);
95         gnttab_entry(head) = GNTTAB_LIST_END;
96
97         spin_unlock_irqrestore(&gnttab_list_lock, flags);
98
99         return ref;
100 }
101
102 #define get_free_entry() get_free_entries(1)
103
104 static void do_free_callbacks(void)
105 {
106         struct gnttab_free_callback *callback, *next;
107
108         callback = gnttab_free_callback_list;
109         gnttab_free_callback_list = NULL;
110
111         while (callback != NULL) {
112                 next = callback->next;
113                 if (gnttab_free_count >= callback->count) {
114                         callback->next = NULL;
115                         callback->queued = 0;
116                         callback->fn(callback->arg);
117                 } else {
118                         callback->next = gnttab_free_callback_list;
119                         gnttab_free_callback_list = callback;
120                 }
121                 callback = next;
122         }
123 }
124
125 static inline void check_free_callbacks(void)
126 {
127         if (unlikely(gnttab_free_callback_list))
128                 do_free_callbacks();
129 }
130
131 static void put_free_entry(grant_ref_t ref)
132 {
133         unsigned long flags;
134         spin_lock_irqsave(&gnttab_list_lock, flags);
135         gnttab_entry(ref) = gnttab_free_head;
136         gnttab_free_head = ref;
137         gnttab_free_count++;
138         check_free_callbacks();
139         spin_unlock_irqrestore(&gnttab_list_lock, flags);
140 }
141
142 /*
143  * Public grant-issuing interface functions
144  */
145
146 int gnttab_grant_foreign_access(domid_t domid, unsigned long frame,
147                                 int flags)
148 {
149         int ref;
150
151         if (unlikely((ref = get_free_entry()) < 0))
152                 return -ENOSPC;
153
154         shared[ref].frame = frame;
155         shared[ref].domid = domid;
156         wmb();
157         BUG_ON(flags & (GTF_accept_transfer | GTF_reading | GTF_writing));
158         shared[ref].flags = GTF_permit_access | flags;
159
160         return ref;
161 }
162 EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access);
163
164 void gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid,
165                                      unsigned long frame, int flags)
166 {
167         shared[ref].frame = frame;
168         shared[ref].domid = domid;
169         wmb();
170         BUG_ON(flags & (GTF_accept_transfer | GTF_reading | GTF_writing));
171         shared[ref].flags = GTF_permit_access | flags;
172 }
173 EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access_ref);
174
175
176 int gnttab_query_foreign_access(grant_ref_t ref)
177 {
178         u16 nflags;
179
180         nflags = shared[ref].flags;
181
182         return (nflags & (GTF_reading|GTF_writing));
183 }
184 EXPORT_SYMBOL_GPL(gnttab_query_foreign_access);
185
186 int gnttab_end_foreign_access_ref(grant_ref_t ref)
187 {
188         u16 flags, nflags;
189
190         nflags = shared[ref].flags;
191         do {
192                 if ((flags = nflags) & (GTF_reading|GTF_writing)) {
193                         printk(KERN_DEBUG "WARNING: g.e. still in use!\n");
194                         return 0;
195                 }
196         } while ((nflags = sync_cmpxchg(&shared[ref].flags, flags, 0)) !=
197                  flags);
198
199         return 1;
200 }
201 EXPORT_SYMBOL_GPL(gnttab_end_foreign_access_ref);
202
203 void gnttab_end_foreign_access(grant_ref_t ref, unsigned long page)
204 {
205         if (gnttab_end_foreign_access_ref(ref)) {
206                 put_free_entry(ref);
207                 if (page != 0)
208                         free_page(page);
209         } else {
210                 /* XXX This needs to be fixed so that the ref and page are
211                    placed on a list to be freed up later. */
212                 printk(KERN_DEBUG
213                        "WARNING: leaking g.e. and page still in use!\n");
214         }
215 }
216 EXPORT_SYMBOL_GPL(gnttab_end_foreign_access);
217
218 int gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn)
219 {
220         int ref;
221
222         if (unlikely((ref = get_free_entry()) < 0))
223                 return -ENOSPC;
224         gnttab_grant_foreign_transfer_ref(ref, domid, pfn);
225
226         return ref;
227 }
228 EXPORT_SYMBOL_GPL(gnttab_grant_foreign_transfer);
229
230 void gnttab_grant_foreign_transfer_ref(grant_ref_t ref, domid_t domid,
231                                        unsigned long pfn)
232 {
233         shared[ref].frame = pfn;
234         shared[ref].domid = domid;
235         wmb();
236         shared[ref].flags = GTF_accept_transfer;
237 }
238 EXPORT_SYMBOL_GPL(gnttab_grant_foreign_transfer_ref);
239
240 unsigned long gnttab_end_foreign_transfer_ref(grant_ref_t ref)
241 {
242         unsigned long frame;
243         u16           flags;
244
245         /*
246          * If a transfer is not even yet started, try to reclaim the grant
247          * reference and return failure (== 0).
248          */
249         while (!((flags = shared[ref].flags) & GTF_transfer_committed)) {
250                 if (sync_cmpxchg(&shared[ref].flags, flags, 0) == flags)
251                         return 0;
252                 cpu_relax();
253         }
254
255         /* If a transfer is in progress then wait until it is completed. */
256         while (!(flags & GTF_transfer_completed)) {
257                 flags = shared[ref].flags;
258                 cpu_relax();
259         }
260
261         /* Read the frame number /after/ reading completion status. */
262         rmb();
263         frame = shared[ref].frame;
264         BUG_ON(frame == 0);
265
266         return frame;
267 }
268 EXPORT_SYMBOL_GPL(gnttab_end_foreign_transfer_ref);
269
270 unsigned long gnttab_end_foreign_transfer(grant_ref_t ref)
271 {
272         unsigned long frame = gnttab_end_foreign_transfer_ref(ref);
273         put_free_entry(ref);
274         return frame;
275 }
276 EXPORT_SYMBOL_GPL(gnttab_end_foreign_transfer);
277
278 void gnttab_free_grant_reference(grant_ref_t ref)
279 {
280         put_free_entry(ref);
281 }
282 EXPORT_SYMBOL_GPL(gnttab_free_grant_reference);
283
284 void gnttab_free_grant_references(grant_ref_t head)
285 {
286         grant_ref_t ref;
287         unsigned long flags;
288         int count = 1;
289         if (head == GNTTAB_LIST_END)
290                 return;
291         spin_lock_irqsave(&gnttab_list_lock, flags);
292         ref = head;
293         while (gnttab_entry(ref) != GNTTAB_LIST_END) {
294                 ref = gnttab_entry(ref);
295                 count++;
296         }
297         gnttab_entry(ref) = gnttab_free_head;
298         gnttab_free_head = head;
299         gnttab_free_count += count;
300         check_free_callbacks();
301         spin_unlock_irqrestore(&gnttab_list_lock, flags);
302 }
303 EXPORT_SYMBOL_GPL(gnttab_free_grant_references);
304
305 int gnttab_alloc_grant_references(u16 count, grant_ref_t *head)
306 {
307         int h = get_free_entries(count);
308
309         if (h < 0)
310                 return -ENOSPC;
311
312         *head = h;
313
314         return 0;
315 }
316 EXPORT_SYMBOL_GPL(gnttab_alloc_grant_references);
317
318 int gnttab_empty_grant_references(const grant_ref_t *private_head)
319 {
320         return (*private_head == GNTTAB_LIST_END);
321 }
322 EXPORT_SYMBOL_GPL(gnttab_empty_grant_references);
323
324 int gnttab_claim_grant_reference(grant_ref_t *private_head)
325 {
326         grant_ref_t g = *private_head;
327         if (unlikely(g == GNTTAB_LIST_END))
328                 return -ENOSPC;
329         *private_head = gnttab_entry(g);
330         return g;
331 }
332 EXPORT_SYMBOL_GPL(gnttab_claim_grant_reference);
333
334 void gnttab_release_grant_reference(grant_ref_t *private_head,
335                                     grant_ref_t release)
336 {
337         gnttab_entry(release) = *private_head;
338         *private_head = release;
339 }
340 EXPORT_SYMBOL_GPL(gnttab_release_grant_reference);
341
342 void gnttab_request_free_callback(struct gnttab_free_callback *callback,
343                                   void (*fn)(void *), void *arg, u16 count)
344 {
345         unsigned long flags;
346         spin_lock_irqsave(&gnttab_list_lock, flags);
347         if (callback->queued)
348                 goto out;
349         callback->fn = fn;
350         callback->arg = arg;
351         callback->count = count;
352         callback->queued = 1;
353         callback->next = gnttab_free_callback_list;
354         gnttab_free_callback_list = callback;
355         check_free_callbacks();
356 out:
357         spin_unlock_irqrestore(&gnttab_list_lock, flags);
358 }
359 EXPORT_SYMBOL_GPL(gnttab_request_free_callback);
360
361 void gnttab_cancel_free_callback(struct gnttab_free_callback *callback)
362 {
363         struct gnttab_free_callback **pcb;
364         unsigned long flags;
365
366         spin_lock_irqsave(&gnttab_list_lock, flags);
367         for (pcb = &gnttab_free_callback_list; *pcb; pcb = &(*pcb)->next) {
368                 if (*pcb == callback) {
369                         *pcb = callback->next;
370                         callback->queued = 0;
371                         break;
372                 }
373         }
374         spin_unlock_irqrestore(&gnttab_list_lock, flags);
375 }
376 EXPORT_SYMBOL_GPL(gnttab_cancel_free_callback);
377
378 static int grow_gnttab_list(unsigned int more_frames)
379 {
380         unsigned int new_nr_grant_frames, extra_entries, i;
381         unsigned int nr_glist_frames, new_nr_glist_frames;
382
383         new_nr_grant_frames = nr_grant_frames + more_frames;
384         extra_entries       = more_frames * ENTRIES_PER_GRANT_FRAME;
385
386         nr_glist_frames = nr_freelist_frames(nr_grant_frames);
387         new_nr_glist_frames = nr_freelist_frames(new_nr_grant_frames);
388         for (i = nr_glist_frames; i < new_nr_glist_frames; i++) {
389                 gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_ATOMIC);
390                 if (!gnttab_list[i])
391                         goto grow_nomem;
392         }
393
394         for (i = ENTRIES_PER_GRANT_FRAME * nr_grant_frames;
395              i < ENTRIES_PER_GRANT_FRAME * new_nr_grant_frames - 1; i++)
396                 gnttab_entry(i) = i + 1;
397
398         gnttab_entry(i) = gnttab_free_head;
399         gnttab_free_head = ENTRIES_PER_GRANT_FRAME * nr_grant_frames;
400         gnttab_free_count += extra_entries;
401
402         nr_grant_frames = new_nr_grant_frames;
403
404         check_free_callbacks();
405
406         return 0;
407         
408 grow_nomem:
409         for ( ; i >= nr_glist_frames; i--)
410                 free_page((unsigned long) gnttab_list[i]);
411         return -ENOMEM;
412 }
413
414 static unsigned int __max_nr_grant_frames(void)
415 {
416         struct gnttab_query_size query;
417         int rc;
418
419         query.dom = DOMID_SELF;
420
421         rc = HYPERVISOR_grant_table_op(GNTTABOP_query_size, &query, 1);
422         if ((rc < 0) || (query.status != GNTST_okay))
423                 return 4; /* Legacy max supported number of frames */
424
425         return query.max_nr_frames;
426 }
427
428 static inline unsigned int max_nr_grant_frames(void)
429 {
430         unsigned int xen_max = __max_nr_grant_frames();
431
432         if (xen_max > boot_max_nr_grant_frames)
433                 return boot_max_nr_grant_frames;
434         return xen_max;
435 }
436
437 #ifdef CONFIG_XEN
438
439 #ifdef CONFIG_X86
440 static int map_pte_fn(pte_t *pte, struct page *pmd_page,
441                       unsigned long addr, void *data)
442 {
443         unsigned long **frames = (unsigned long **)data;
444
445         set_pte_at(&init_mm, addr, pte, pfn_pte_ma((*frames)[0], PAGE_KERNEL));
446         (*frames)++;
447         return 0;
448 }
449
450 #ifdef CONFIG_PM_SLEEP
451 static int unmap_pte_fn(pte_t *pte, struct page *pmd_page,
452                         unsigned long addr, void *data)
453 {
454
455         set_pte_at(&init_mm, addr, pte, __pte(0));
456         return 0;
457 }
458 #endif
459
460 void *arch_gnttab_alloc_shared(unsigned long *frames)
461 {
462         struct vm_struct *area;
463         area = alloc_vm_area(PAGE_SIZE * max_nr_grant_frames(), NULL);
464         BUG_ON(area == NULL);
465         return area->addr;
466 }
467 #endif /* CONFIG_X86 */
468
469 static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
470 {
471         struct gnttab_setup_table setup;
472         unsigned long *frames;
473         unsigned int nr_gframes = end_idx + 1;
474         int rc;
475
476         frames = kmalloc(nr_gframes * sizeof(unsigned long), GFP_ATOMIC);
477         if (!frames)
478                 return -ENOMEM;
479
480         setup.dom        = DOMID_SELF;
481         setup.nr_frames  = nr_gframes;
482         set_xen_guest_handle(setup.frame_list, frames);
483
484         rc = HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
485         if (rc == -ENOSYS) {
486                 kfree(frames);
487                 return -ENOSYS;
488         }
489
490         BUG_ON(rc || setup.status != GNTST_okay);
491
492         if (shared == NULL)
493                 shared = arch_gnttab_alloc_shared(frames);
494
495 #ifdef CONFIG_X86
496         rc = apply_to_page_range(&init_mm, (unsigned long)shared,
497                                  PAGE_SIZE * nr_gframes,
498                                  map_pte_fn, &frames);
499         BUG_ON(rc);
500         frames -= nr_gframes; /* adjust after map_pte_fn() */
501 #endif /* CONFIG_X86 */
502
503         kfree(frames);
504
505         return 0;
506 }
507
508 #if defined(CONFIG_XEN_BACKEND) || defined(CONFIG_XEN_BACKEND_MODULE)
509
510 static DEFINE_SEQLOCK(gnttab_dma_lock);
511
512 static void gnttab_page_free(struct page *page, unsigned int order)
513 {
514         BUG_ON(order);
515         ClearPageForeign(page);
516         gnttab_reset_grant_page(page);
517         ClearPageReserved(page);
518         put_page(page);
519 }
520
521 /*
522  * Must not be called with IRQs off.  This should only be used on the
523  * slow path.
524  *
525  * Copy a foreign granted page to local memory.
526  */
527 int gnttab_copy_grant_page(grant_ref_t ref, struct page **pagep)
528 {
529         struct gnttab_unmap_and_replace unmap;
530         mmu_update_t mmu;
531         struct page *page;
532         struct page *new_page;
533         void *new_addr;
534         void *addr;
535         paddr_t pfn;
536         maddr_t mfn;
537         maddr_t new_mfn;
538         int err;
539
540         page = *pagep;
541         if (!get_page_unless_zero(page))
542                 return -ENOENT;
543
544         err = -ENOMEM;
545         new_page = alloc_page(GFP_ATOMIC | __GFP_NOWARN);
546         if (!new_page)
547                 goto out;
548
549         new_addr = page_address(new_page);
550         addr = page_address(page);
551         copy_page(new_addr, addr);
552
553         pfn = page_to_pfn(page);
554         mfn = pfn_to_mfn(pfn);
555         new_mfn = virt_to_mfn(new_addr);
556
557         write_seqlock_bh(&gnttab_dma_lock);
558
559         /* Make seq visible before checking page_mapped. */
560         smp_mb();
561
562         /* Has the page been DMA-mapped? */
563         if (unlikely(page_mapped(page))) {
564                 write_sequnlock_bh(&gnttab_dma_lock);
565                 put_page(new_page);
566                 err = -EBUSY;
567                 goto out;
568         }
569
570         if (!xen_feature(XENFEAT_auto_translated_physmap))
571                 set_phys_to_machine(pfn, new_mfn);
572
573         gnttab_set_replace_op(&unmap, (unsigned long)addr,
574                               (unsigned long)new_addr, ref);
575
576         err = HYPERVISOR_grant_table_op(GNTTABOP_unmap_and_replace,
577                                         &unmap, 1);
578         BUG_ON(err);
579         BUG_ON(unmap.status != GNTST_okay);
580
581         write_sequnlock_bh(&gnttab_dma_lock);
582
583         if (!xen_feature(XENFEAT_auto_translated_physmap)) {
584                 set_phys_to_machine(page_to_pfn(new_page), INVALID_P2M_ENTRY);
585
586                 mmu.ptr = (new_mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
587                 mmu.val = pfn;
588                 err = HYPERVISOR_mmu_update(&mmu, 1, NULL, DOMID_SELF);
589                 BUG_ON(err);
590         }
591
592         new_page->mapping = page->mapping;
593         new_page->index = page->index;
594         set_bit(PG_foreign, &new_page->flags);
595         if (PageReserved(page))
596                 SetPageReserved(new_page);
597         *pagep = new_page;
598
599         SetPageForeign(page, gnttab_page_free);
600         page->mapping = NULL;
601
602 out:
603         put_page(page);
604         return err;
605 }
606 EXPORT_SYMBOL_GPL(gnttab_copy_grant_page);
607
608 void gnttab_reset_grant_page(struct page *page)
609 {
610         init_page_count(page);
611         reset_page_mapcount(page);
612 }
613 EXPORT_SYMBOL_GPL(gnttab_reset_grant_page);
614
615 /*
616  * Keep track of foreign pages marked as PageForeign so that we don't
617  * return them to the remote domain prematurely.
618  *
619  * PageForeign pages are pinned down by increasing their mapcount.
620  *
621  * All other pages are simply returned as is.
622  */
623 void __gnttab_dma_map_page(struct page *page)
624 {
625         unsigned int seq;
626
627         if (!is_running_on_xen() || !PageForeign(page))
628                 return;
629
630         do {
631                 seq = read_seqbegin(&gnttab_dma_lock);
632
633                 if (gnttab_dma_local_pfn(page))
634                         break;
635
636                 atomic_set(&page->_mapcount, 0);
637
638                 /* Make _mapcount visible before read_seqretry. */
639                 smp_mb();
640         } while (unlikely(read_seqretry(&gnttab_dma_lock, seq)));
641 }
642
643 #endif /* CONFIG_XEN_BACKEND */
644
645 #ifdef __HAVE_ARCH_PTE_SPECIAL
646
647 static unsigned int GNTMAP_pte_special;
648
649 bool gnttab_pre_map_adjust(unsigned int cmd, struct gnttab_map_grant_ref *map,
650                            unsigned int count)
651 {
652         unsigned int i;
653
654         if (unlikely(cmd != GNTTABOP_map_grant_ref))
655                 count = 0;
656
657         for (i = 0; i < count; ++i, ++map) {
658                 if (!(map->flags & GNTMAP_host_map)
659                     || !(map->flags & GNTMAP_application_map))
660                         continue;
661                 if (GNTMAP_pte_special)
662                         map->flags |= GNTMAP_pte_special;
663                 else {
664                         BUG_ON(xen_feature(XENFEAT_auto_translated_physmap));
665                         return true;
666                 }
667         }
668
669         return false;
670 }
671 EXPORT_SYMBOL(gnttab_pre_map_adjust);
672
673 #if CONFIG_XEN_COMPAT < 0x030400
674 int gnttab_post_map_adjust(const struct gnttab_map_grant_ref *map, unsigned int count)
675 {
676         unsigned int i;
677         int rc = 0;
678
679         for (i = 0; i < count && rc == 0; ++i, ++map) {
680                 pte_t pte;
681
682                 if (!(map->flags & GNTMAP_host_map)
683                     || !(map->flags & GNTMAP_application_map))
684                         continue;
685
686 #ifdef CONFIG_X86
687                 pte = __pte_ma((map->dev_bus_addr | _PAGE_PRESENT | _PAGE_USER
688                                 | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_NX
689                                 | _PAGE_SPECIAL)
690                                & __supported_pte_mask);
691 #else
692 #error Architecture not yet supported.
693 #endif
694                 if (!(map->flags & GNTMAP_readonly))
695                         pte = pte_mkwrite(pte);
696
697                 if (map->flags & GNTMAP_contains_pte) {
698                         mmu_update_t u;
699
700                         u.ptr = map->host_addr;
701                         u.val = __pte_val(pte);
702                         rc = HYPERVISOR_mmu_update(&u, 1, NULL, DOMID_SELF);
703                 } else
704                         rc = HYPERVISOR_update_va_mapping(map->host_addr, pte, 0);
705         }
706
707         return rc;
708 }
709 EXPORT_SYMBOL(gnttab_post_map_adjust);
710 #endif
711
712 #endif /* __HAVE_ARCH_PTE_SPECIAL */
713
714 int gnttab_resume(void)
715 {
716         if (max_nr_grant_frames() < nr_grant_frames)
717                 return 0;
718         return gnttab_map(0, nr_grant_frames - 1);
719 }
720
721 #ifdef CONFIG_PM_SLEEP
722 #include <linux/syscore_ops.h>
723
724 #ifdef CONFIG_X86
725 static int gnttab_suspend(void)
726 {
727         apply_to_page_range(&init_mm, (unsigned long)shared,
728                             PAGE_SIZE * nr_grant_frames,
729                             unmap_pte_fn, NULL);
730         return 0;
731 }
732 #else
733 #define gnttab_suspend NULL
734 #endif
735
736 static void _gnttab_resume(void)
737 {
738         if (gnttab_resume())
739                 BUG();
740 }
741
742 static struct syscore_ops gnttab_syscore_ops = {
743         .resume         = _gnttab_resume,
744         .suspend        = gnttab_suspend,
745 };
746 #endif
747
748 #else /* !CONFIG_XEN */
749
750 #include <platform-pci.h>
751
752 static unsigned long resume_frames;
753
754 static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
755 {
756         struct xen_add_to_physmap xatp;
757         unsigned int i = end_idx;
758
759         /* Loop backwards, so that the first hypercall has the largest index,
760          * ensuring that the table will grow only once.
761          */
762         do {
763                 xatp.domid = DOMID_SELF;
764                 xatp.idx = i;
765                 xatp.space = XENMAPSPACE_grant_table;
766                 xatp.gpfn = (resume_frames >> PAGE_SHIFT) + i;
767                 if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp))
768                         BUG();
769         } while (i-- > start_idx);
770
771         return 0;
772 }
773
774 int gnttab_resume(void)
775 {
776         unsigned int max_nr_gframes, nr_gframes;
777
778         nr_gframes = nr_grant_frames;
779         max_nr_gframes = max_nr_grant_frames();
780         if (max_nr_gframes < nr_gframes)
781                 return -ENOSYS;
782
783         if (!resume_frames) {
784                 resume_frames = alloc_xen_mmio(PAGE_SIZE * max_nr_gframes);
785                 shared = ioremap(resume_frames, PAGE_SIZE * max_nr_gframes);
786                 if (shared == NULL) {
787                         pr_warning("error to ioremap gnttab share frames\n");
788                         return -1;
789                 }
790         }
791
792         gnttab_map(0, nr_gframes - 1);
793
794         return 0;
795 }
796
797 #endif /* !CONFIG_XEN */
798
799 static int gnttab_expand(unsigned int req_entries)
800 {
801         int rc;
802         unsigned int cur, extra;
803
804         cur = nr_grant_frames;
805         extra = ((req_entries + (ENTRIES_PER_GRANT_FRAME-1)) /
806                  ENTRIES_PER_GRANT_FRAME);
807         if (cur + extra > max_nr_grant_frames())
808                 return -ENOSPC;
809
810         if ((rc = gnttab_map(cur, cur + extra - 1)) == 0)
811                 rc = grow_gnttab_list(extra);
812
813         return rc;
814 }
815
816 #ifdef CONFIG_XEN
817 static int __init
818 #else
819 int __devinit
820 #endif
821 gnttab_init(void)
822 {
823         int i;
824         unsigned int max_nr_glist_frames, nr_glist_frames;
825         unsigned int nr_init_grefs;
826
827         if (!is_running_on_xen())
828                 return -ENODEV;
829
830         nr_grant_frames = 1;
831         boot_max_nr_grant_frames = __max_nr_grant_frames();
832
833         /* Determine the maximum number of frames required for the
834          * grant reference free list on the current hypervisor.
835          */
836         max_nr_glist_frames = nr_freelist_frames(boot_max_nr_grant_frames);
837
838         gnttab_list = kmalloc(max_nr_glist_frames * sizeof(grant_ref_t *),
839                               GFP_KERNEL);
840         if (gnttab_list == NULL)
841                 return -ENOMEM;
842
843         nr_glist_frames = nr_freelist_frames(nr_grant_frames);
844         for (i = 0; i < nr_glist_frames; i++) {
845                 gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_KERNEL);
846                 if (gnttab_list[i] == NULL)
847                         goto ini_nomem;
848         }
849
850         if (gnttab_resume() < 0)
851                 return -ENODEV;
852
853         nr_init_grefs = nr_grant_frames * ENTRIES_PER_GRANT_FRAME;
854
855         for (i = NR_RESERVED_ENTRIES; i < nr_init_grefs - 1; i++)
856                 gnttab_entry(i) = i + 1;
857
858         gnttab_entry(nr_init_grefs - 1) = GNTTAB_LIST_END;
859         gnttab_free_count = nr_init_grefs - NR_RESERVED_ENTRIES;
860         gnttab_free_head  = NR_RESERVED_ENTRIES;
861
862 #if defined(CONFIG_XEN) && defined(__HAVE_ARCH_PTE_SPECIAL)
863         if (!xen_feature(XENFEAT_auto_translated_physmap)
864             && xen_feature(XENFEAT_gnttab_map_avail_bits)) {
865 #ifdef CONFIG_X86
866                 GNTMAP_pte_special = (__pte_val(pte_mkspecial(__pte_ma(0)))
867                                       >> _PAGE_BIT_UNUSED1) << _GNTMAP_guest_avail0;
868 #else
869 #error Architecture not yet supported.
870 #endif
871         }
872 #endif
873
874 #if defined(CONFIG_XEN) && defined(CONFIG_PM_SLEEP)
875         if (!is_initial_xendomain())
876                 register_syscore_ops(&gnttab_syscore_ops);
877 #endif
878
879         return 0;
880
881  ini_nomem:
882         for (i--; i >= 0; i--)
883                 free_page((unsigned long)gnttab_list[i]);
884         kfree(gnttab_list);
885         return -ENOMEM;
886 }
887
888 #ifdef CONFIG_XEN
889 core_initcall(gnttab_init);
890 #endif