diff options
author | Jennifer Herbert <jennifer.herbert@citrix.com> | 2014-12-24 09:17:06 -0500 |
---|---|---|
committer | David Vrabel <david.vrabel@citrix.com> | 2015-01-28 09:03:12 -0500 |
commit | 8da7633f168b5428e2cfb7342408b2c44088f5df (patch) | |
tree | 33e17f065d1aa9bf8a57ac03b737154bac0d3468 | |
parent | ff4b156f166b3931894d2a8b5cdba6cdf4da0618 (diff) |
xen: mark grant mapped pages as foreign
Use the "foreign" page flag to mark pages that have a grant map. Use
page->private to store information of the grant (the granting domain
and the grant reference).
Signed-off-by: Jennifer Herbert <jennifer.herbert@citrix.com>
Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Signed-off-by: David Vrabel <david.vrabel@citrix.com>
-rw-r--r-- | arch/x86/xen/p2m.c | 7 | ||||
-rw-r--r-- | drivers/xen/grant-table.c | 43 | ||||
-rw-r--r-- | include/xen/grant_table.h | 20 |
3 files changed, 61 insertions, 9 deletions
diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c index a8691cb08420..f18fd1d411f6 100644 --- a/arch/x86/xen/p2m.c +++ b/arch/x86/xen/p2m.c | |||
@@ -681,12 +681,8 @@ int set_foreign_p2m_mapping(struct gnttab_map_grant_ref *map_ops, | |||
681 | } | 681 | } |
682 | pfn = page_to_pfn(pages[i]); | 682 | pfn = page_to_pfn(pages[i]); |
683 | 683 | ||
684 | WARN_ON(PagePrivate(pages[i])); | ||
685 | WARN(pfn_to_mfn(pfn) != INVALID_P2M_ENTRY, "page must be ballooned"); | 684 | WARN(pfn_to_mfn(pfn) != INVALID_P2M_ENTRY, "page must be ballooned"); |
686 | 685 | ||
687 | SetPagePrivate(pages[i]); | ||
688 | set_page_private(pages[i], mfn); | ||
689 | |||
690 | if (unlikely(!set_phys_to_machine(pfn, FOREIGN_FRAME(mfn)))) { | 686 | if (unlikely(!set_phys_to_machine(pfn, FOREIGN_FRAME(mfn)))) { |
691 | ret = -ENOMEM; | 687 | ret = -ENOMEM; |
692 | goto out; | 688 | goto out; |
@@ -716,9 +712,6 @@ int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops, | |||
716 | goto out; | 712 | goto out; |
717 | } | 713 | } |
718 | 714 | ||
719 | set_page_private(pages[i], INVALID_P2M_ENTRY); | ||
720 | WARN_ON(!PagePrivate(pages[i])); | ||
721 | ClearPagePrivate(pages[i]); | ||
722 | set_phys_to_machine(pfn, INVALID_P2M_ENTRY); | 715 | set_phys_to_machine(pfn, INVALID_P2M_ENTRY); |
723 | } | 716 | } |
724 | if (kunmap_ops) | 717 | if (kunmap_ops) |
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index b4f93c490f83..89dcca448bb6 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c | |||
@@ -679,12 +679,27 @@ EXPORT_SYMBOL_GPL(gnttab_free_auto_xlat_frames); | |||
679 | */ | 679 | */ |
680 | int gnttab_alloc_pages(int nr_pages, struct page **pages) | 680 | int gnttab_alloc_pages(int nr_pages, struct page **pages) |
681 | { | 681 | { |
682 | int i; | ||
682 | int ret; | 683 | int ret; |
683 | 684 | ||
684 | ret = alloc_xenballooned_pages(nr_pages, pages, false); | 685 | ret = alloc_xenballooned_pages(nr_pages, pages, false); |
685 | if (ret < 0) | 686 | if (ret < 0) |
686 | return ret; | 687 | return ret; |
687 | 688 | ||
689 | for (i = 0; i < nr_pages; i++) { | ||
690 | #if BITS_PER_LONG < 64 | ||
691 | struct xen_page_foreign *foreign; | ||
692 | |||
693 | foreign = kzalloc(sizeof(*foreign), GFP_KERNEL); | ||
694 | if (!foreign) { | ||
695 | gnttab_free_pages(nr_pages, pages); | ||
696 | return -ENOMEM; | ||
697 | } | ||
698 | set_page_private(pages[i], (unsigned long)foreign); | ||
699 | #endif | ||
700 | SetPagePrivate(pages[i]); | ||
701 | } | ||
702 | |||
688 | return 0; | 703 | return 0; |
689 | } | 704 | } |
690 | EXPORT_SYMBOL(gnttab_alloc_pages); | 705 | EXPORT_SYMBOL(gnttab_alloc_pages); |
@@ -696,6 +711,16 @@ EXPORT_SYMBOL(gnttab_alloc_pages); | |||
696 | */ | 711 | */ |
697 | void gnttab_free_pages(int nr_pages, struct page **pages) | 712 | void gnttab_free_pages(int nr_pages, struct page **pages) |
698 | { | 713 | { |
714 | int i; | ||
715 | |||
716 | for (i = 0; i < nr_pages; i++) { | ||
717 | if (PagePrivate(pages[i])) { | ||
718 | #if BITS_PER_LONG < 64 | ||
719 | kfree((void *)page_private(pages[i])); | ||
720 | #endif | ||
721 | ClearPagePrivate(pages[i]); | ||
722 | } | ||
723 | } | ||
699 | free_xenballooned_pages(nr_pages, pages); | 724 | free_xenballooned_pages(nr_pages, pages); |
700 | } | 725 | } |
701 | EXPORT_SYMBOL(gnttab_free_pages); | 726 | EXPORT_SYMBOL(gnttab_free_pages); |
@@ -756,12 +781,22 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops, | |||
756 | if (ret) | 781 | if (ret) |
757 | return ret; | 782 | return ret; |
758 | 783 | ||
759 | /* Retry eagain maps */ | 784 | for (i = 0; i < count; i++) { |
760 | for (i = 0; i < count; i++) | 785 | /* Retry eagain maps */ |
761 | if (map_ops[i].status == GNTST_eagain) | 786 | if (map_ops[i].status == GNTST_eagain) |
762 | gnttab_retry_eagain_gop(GNTTABOP_map_grant_ref, map_ops + i, | 787 | gnttab_retry_eagain_gop(GNTTABOP_map_grant_ref, map_ops + i, |
763 | &map_ops[i].status, __func__); | 788 | &map_ops[i].status, __func__); |
764 | 789 | ||
790 | if (map_ops[i].status == GNTST_okay) { | ||
791 | struct xen_page_foreign *foreign; | ||
792 | |||
793 | SetPageForeign(pages[i]); | ||
794 | foreign = xen_page_foreign(pages[i]); | ||
795 | foreign->domid = map_ops[i].dom; | ||
796 | foreign->gref = map_ops[i].ref; | ||
797 | } | ||
798 | } | ||
799 | |||
765 | return set_foreign_p2m_mapping(map_ops, kmap_ops, pages, count); | 800 | return set_foreign_p2m_mapping(map_ops, kmap_ops, pages, count); |
766 | } | 801 | } |
767 | EXPORT_SYMBOL_GPL(gnttab_map_refs); | 802 | EXPORT_SYMBOL_GPL(gnttab_map_refs); |
@@ -770,12 +805,16 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops, | |||
770 | struct gnttab_unmap_grant_ref *kunmap_ops, | 805 | struct gnttab_unmap_grant_ref *kunmap_ops, |
771 | struct page **pages, unsigned int count) | 806 | struct page **pages, unsigned int count) |
772 | { | 807 | { |
808 | unsigned int i; | ||
773 | int ret; | 809 | int ret; |
774 | 810 | ||
775 | ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, unmap_ops, count); | 811 | ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, unmap_ops, count); |
776 | if (ret) | 812 | if (ret) |
777 | return ret; | 813 | return ret; |
778 | 814 | ||
815 | for (i = 0; i < count; i++) | ||
816 | ClearPageForeign(pages[i]); | ||
817 | |||
779 | return clear_foreign_p2m_mapping(unmap_ops, kunmap_ops, pages, count); | 818 | return clear_foreign_p2m_mapping(unmap_ops, kunmap_ops, pages, count); |
780 | } | 819 | } |
781 | EXPORT_SYMBOL_GPL(gnttab_unmap_refs); | 820 | EXPORT_SYMBOL_GPL(gnttab_unmap_refs); |
diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h index 949803e20872..d3bef563e8da 100644 --- a/include/xen/grant_table.h +++ b/include/xen/grant_table.h | |||
@@ -45,6 +45,8 @@ | |||
45 | #include <asm/xen/hypervisor.h> | 45 | #include <asm/xen/hypervisor.h> |
46 | 46 | ||
47 | #include <xen/features.h> | 47 | #include <xen/features.h> |
48 | #include <linux/mm_types.h> | ||
49 | #include <linux/page-flags.h> | ||
48 | 50 | ||
49 | #define GNTTAB_RESERVED_XENSTORE 1 | 51 | #define GNTTAB_RESERVED_XENSTORE 1 |
50 | 52 | ||
@@ -185,4 +187,22 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops, | |||
185 | void gnttab_batch_map(struct gnttab_map_grant_ref *batch, unsigned count); | 187 | void gnttab_batch_map(struct gnttab_map_grant_ref *batch, unsigned count); |
186 | void gnttab_batch_copy(struct gnttab_copy *batch, unsigned count); | 188 | void gnttab_batch_copy(struct gnttab_copy *batch, unsigned count); |
187 | 189 | ||
190 | |||
191 | struct xen_page_foreign { | ||
192 | domid_t domid; | ||
193 | grant_ref_t gref; | ||
194 | }; | ||
195 | |||
196 | static inline struct xen_page_foreign *xen_page_foreign(struct page *page) | ||
197 | { | ||
198 | if (!PageForeign(page)) | ||
199 | return NULL; | ||
200 | #if BITS_PER_LONG < 64 | ||
201 | return (struct xen_page_foreign *)page->private; | ||
202 | #else | ||
203 | BUILD_BUG_ON(sizeof(struct xen_page_foreign) > BITS_PER_LONG); | ||
204 | return (struct xen_page_foreign *)&page->private; | ||
205 | #endif | ||
206 | } | ||
207 | |||
188 | #endif /* __ASM_GNTTAB_H__ */ | 208 | #endif /* __ASM_GNTTAB_H__ */ |