diff options
Diffstat (limited to 'drivers/xen/grant-table.c')
-rw-r--r-- | drivers/xen/grant-table.c | 58 |
1 files changed, 51 insertions, 7 deletions
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index e69c7780c208..44b75ccfbbff 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c | |||
@@ -65,8 +65,7 @@ static unsigned int nr_grant_frames; | |||
65 | static int gnttab_free_count; | 65 | static int gnttab_free_count; |
66 | static grant_ref_t gnttab_free_head; | 66 | static grant_ref_t gnttab_free_head; |
67 | static DEFINE_SPINLOCK(gnttab_list_lock); | 67 | static DEFINE_SPINLOCK(gnttab_list_lock); |
68 | unsigned long xen_hvm_resume_frames; | 68 | struct grant_frames xen_auto_xlat_grant_frames; |
69 | EXPORT_SYMBOL_GPL(xen_hvm_resume_frames); | ||
70 | 69 | ||
71 | static union { | 70 | static union { |
72 | struct grant_entry_v1 *v1; | 71 | struct grant_entry_v1 *v1; |
@@ -838,6 +837,51 @@ unsigned int gnttab_max_grant_frames(void) | |||
838 | } | 837 | } |
839 | EXPORT_SYMBOL_GPL(gnttab_max_grant_frames); | 838 | EXPORT_SYMBOL_GPL(gnttab_max_grant_frames); |
840 | 839 | ||
840 | int gnttab_setup_auto_xlat_frames(unsigned long addr) | ||
841 | { | ||
842 | xen_pfn_t *pfn; | ||
843 | unsigned int max_nr_gframes = __max_nr_grant_frames(); | ||
844 | unsigned int i; | ||
845 | void *vaddr; | ||
846 | |||
847 | if (xen_auto_xlat_grant_frames.count) | ||
848 | return -EINVAL; | ||
849 | |||
850 | vaddr = xen_remap(addr, PAGE_SIZE * max_nr_gframes); | ||
851 | if (vaddr == NULL) { | ||
852 | pr_warn("Failed to ioremap gnttab share frames (addr=0x%08lx)!\n", | ||
853 | addr); | ||
854 | return -ENOMEM; | ||
855 | } | ||
856 | pfn = kcalloc(max_nr_gframes, sizeof(pfn[0]), GFP_KERNEL); | ||
857 | if (!pfn) { | ||
858 | xen_unmap(vaddr); | ||
859 | return -ENOMEM; | ||
860 | } | ||
861 | for (i = 0; i < max_nr_gframes; i++) | ||
862 | pfn[i] = PFN_DOWN(addr) + i; | ||
863 | |||
864 | xen_auto_xlat_grant_frames.vaddr = vaddr; | ||
865 | xen_auto_xlat_grant_frames.pfn = pfn; | ||
866 | xen_auto_xlat_grant_frames.count = max_nr_gframes; | ||
867 | |||
868 | return 0; | ||
869 | } | ||
870 | EXPORT_SYMBOL_GPL(gnttab_setup_auto_xlat_frames); | ||
871 | |||
872 | void gnttab_free_auto_xlat_frames(void) | ||
873 | { | ||
874 | if (!xen_auto_xlat_grant_frames.count) | ||
875 | return; | ||
876 | kfree(xen_auto_xlat_grant_frames.pfn); | ||
877 | xen_unmap(xen_auto_xlat_grant_frames.vaddr); | ||
878 | |||
879 | xen_auto_xlat_grant_frames.pfn = NULL; | ||
880 | xen_auto_xlat_grant_frames.count = 0; | ||
881 | xen_auto_xlat_grant_frames.vaddr = NULL; | ||
882 | } | ||
883 | EXPORT_SYMBOL_GPL(gnttab_free_auto_xlat_frames); | ||
884 | |||
841 | /* Handling of paged out grant targets (GNTST_eagain) */ | 885 | /* Handling of paged out grant targets (GNTST_eagain) */ |
842 | #define MAX_DELAY 256 | 886 | #define MAX_DELAY 256 |
843 | static inline void | 887 | static inline void |
@@ -1068,6 +1112,7 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx) | |||
1068 | struct xen_add_to_physmap xatp; | 1112 | struct xen_add_to_physmap xatp; |
1069 | unsigned int i = end_idx; | 1113 | unsigned int i = end_idx; |
1070 | rc = 0; | 1114 | rc = 0; |
1115 | BUG_ON(xen_auto_xlat_grant_frames.count < nr_gframes); | ||
1071 | /* | 1116 | /* |
1072 | * Loop backwards, so that the first hypercall has the largest | 1117 | * Loop backwards, so that the first hypercall has the largest |
1073 | * index, ensuring that the table will grow only once. | 1118 | * index, ensuring that the table will grow only once. |
@@ -1076,7 +1121,7 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx) | |||
1076 | xatp.domid = DOMID_SELF; | 1121 | xatp.domid = DOMID_SELF; |
1077 | xatp.idx = i; | 1122 | xatp.idx = i; |
1078 | xatp.space = XENMAPSPACE_grant_table; | 1123 | xatp.space = XENMAPSPACE_grant_table; |
1079 | xatp.gpfn = (xen_hvm_resume_frames >> PAGE_SHIFT) + i; | 1124 | xatp.gpfn = xen_auto_xlat_grant_frames.pfn[i]; |
1080 | rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp); | 1125 | rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp); |
1081 | if (rc != 0) { | 1126 | if (rc != 0) { |
1082 | pr_warn("grant table add_to_physmap failed, err=%d\n", | 1127 | pr_warn("grant table add_to_physmap failed, err=%d\n", |
@@ -1174,11 +1219,10 @@ static int gnttab_setup(void) | |||
1174 | return -ENOSYS; | 1219 | return -ENOSYS; |
1175 | 1220 | ||
1176 | if (xen_feature(XENFEAT_auto_translated_physmap) && gnttab_shared.addr == NULL) { | 1221 | if (xen_feature(XENFEAT_auto_translated_physmap) && gnttab_shared.addr == NULL) { |
1177 | gnttab_shared.addr = xen_remap(xen_hvm_resume_frames, | 1222 | gnttab_shared.addr = xen_auto_xlat_grant_frames.vaddr; |
1178 | PAGE_SIZE * max_nr_gframes); | ||
1179 | if (gnttab_shared.addr == NULL) { | 1223 | if (gnttab_shared.addr == NULL) { |
1180 | pr_warn("Failed to ioremap gnttab share frames (addr=0x%08lx)!\n", | 1224 | pr_warn("gnttab share frames (addr=0x%08lx) is not mapped!\n", |
1181 | xen_hvm_resume_frames); | 1225 | (unsigned long)xen_auto_xlat_grant_frames.vaddr); |
1182 | return -ENOMEM; | 1226 | return -ENOMEM; |
1183 | } | 1227 | } |
1184 | } | 1228 | } |