diff options
-rw-r--r-- | arch/arm/include/asm/xen/page.h | 1 | ||||
-rw-r--r-- | arch/arm/xen/enlighten.c | 9 | ||||
-rw-r--r-- | arch/x86/include/asm/xen/page.h | 1 | ||||
-rw-r--r-- | drivers/xen/grant-table.c | 58 | ||||
-rw-r--r-- | drivers/xen/platform-pci.c | 10 | ||||
-rw-r--r-- | include/xen/grant_table.h | 9 |
6 files changed, 75 insertions, 13 deletions
diff --git a/arch/arm/include/asm/xen/page.h b/arch/arm/include/asm/xen/page.h index ac6789aad059..709c4b4d2f1d 100644 --- a/arch/arm/include/asm/xen/page.h +++ b/arch/arm/include/asm/xen/page.h | |||
@@ -118,5 +118,6 @@ static inline bool set_phys_to_machine(unsigned long pfn, unsigned long mfn) | |||
118 | } | 118 | } |
119 | 119 | ||
120 | #define xen_remap(cookie, size) ioremap_cached((cookie), (size)) | 120 | #define xen_remap(cookie, size) ioremap_cached((cookie), (size)) |
121 | #define xen_unmap(cookie) iounmap((cookie)) | ||
121 | 122 | ||
122 | #endif /* _ASM_ARM_XEN_PAGE_H */ | 123 | #endif /* _ASM_ARM_XEN_PAGE_H */ |
diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c index 85501238b425..2162172c0ddc 100644 --- a/arch/arm/xen/enlighten.c +++ b/arch/arm/xen/enlighten.c | |||
@@ -208,6 +208,7 @@ static int __init xen_guest_init(void) | |||
208 | const char *version = NULL; | 208 | const char *version = NULL; |
209 | const char *xen_prefix = "xen,xen-"; | 209 | const char *xen_prefix = "xen,xen-"; |
210 | struct resource res; | 210 | struct resource res; |
211 | unsigned long grant_frames; | ||
211 | 212 | ||
212 | node = of_find_compatible_node(NULL, NULL, "xen,xen"); | 213 | node = of_find_compatible_node(NULL, NULL, "xen,xen"); |
213 | if (!node) { | 214 | if (!node) { |
@@ -224,10 +225,10 @@ static int __init xen_guest_init(void) | |||
224 | } | 225 | } |
225 | if (of_address_to_resource(node, GRANT_TABLE_PHYSADDR, &res)) | 226 | if (of_address_to_resource(node, GRANT_TABLE_PHYSADDR, &res)) |
226 | return 0; | 227 | return 0; |
227 | xen_hvm_resume_frames = res.start; | 228 | grant_frames = res.start; |
228 | xen_events_irq = irq_of_parse_and_map(node, 0); | 229 | xen_events_irq = irq_of_parse_and_map(node, 0); |
229 | pr_info("Xen %s support found, events_irq=%d gnttab_frame_pfn=%lx\n", | 230 | pr_info("Xen %s support found, events_irq=%d gnttab_frame_pfn=%lx\n", |
230 | version, xen_events_irq, (xen_hvm_resume_frames >> PAGE_SHIFT)); | 231 | version, xen_events_irq, (grant_frames >> PAGE_SHIFT)); |
231 | xen_domain_type = XEN_HVM_DOMAIN; | 232 | xen_domain_type = XEN_HVM_DOMAIN; |
232 | 233 | ||
233 | xen_setup_features(); | 234 | xen_setup_features(); |
@@ -265,6 +266,10 @@ static int __init xen_guest_init(void) | |||
265 | if (xen_vcpu_info == NULL) | 266 | if (xen_vcpu_info == NULL) |
266 | return -ENOMEM; | 267 | return -ENOMEM; |
267 | 268 | ||
269 | if (gnttab_setup_auto_xlat_frames(grant_frames)) { | ||
270 | free_percpu(xen_vcpu_info); | ||
271 | return -ENOMEM; | ||
272 | } | ||
268 | gnttab_init(); | 273 | gnttab_init(); |
269 | if (!xen_initial_domain()) | 274 | if (!xen_initial_domain()) |
270 | xenbus_probe(NULL); | 275 | xenbus_probe(NULL); |
diff --git a/arch/x86/include/asm/xen/page.h b/arch/x86/include/asm/xen/page.h index 4a092ccdd147..3e276eb23d1b 100644 --- a/arch/x86/include/asm/xen/page.h +++ b/arch/x86/include/asm/xen/page.h | |||
@@ -227,5 +227,6 @@ void make_lowmem_page_readonly(void *vaddr); | |||
227 | void make_lowmem_page_readwrite(void *vaddr); | 227 | void make_lowmem_page_readwrite(void *vaddr); |
228 | 228 | ||
229 | #define xen_remap(cookie, size) ioremap((cookie), (size)); | 229 | #define xen_remap(cookie, size) ioremap((cookie), (size)); |
230 | #define xen_unmap(cookie) iounmap((cookie)) | ||
230 | 231 | ||
231 | #endif /* _ASM_X86_XEN_PAGE_H */ | 232 | #endif /* _ASM_X86_XEN_PAGE_H */ |
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 | } |
diff --git a/drivers/xen/platform-pci.c b/drivers/xen/platform-pci.c index 2f3528e93cb9..f1947ac218d9 100644 --- a/drivers/xen/platform-pci.c +++ b/drivers/xen/platform-pci.c | |||
@@ -108,6 +108,7 @@ static int platform_pci_init(struct pci_dev *pdev, | |||
108 | long ioaddr; | 108 | long ioaddr; |
109 | long mmio_addr, mmio_len; | 109 | long mmio_addr, mmio_len; |
110 | unsigned int max_nr_gframes; | 110 | unsigned int max_nr_gframes; |
111 | unsigned long grant_frames; | ||
111 | 112 | ||
112 | if (!xen_domain()) | 113 | if (!xen_domain()) |
113 | return -ENODEV; | 114 | return -ENODEV; |
@@ -154,13 +155,16 @@ static int platform_pci_init(struct pci_dev *pdev, | |||
154 | } | 155 | } |
155 | 156 | ||
156 | max_nr_gframes = gnttab_max_grant_frames(); | 157 | max_nr_gframes = gnttab_max_grant_frames(); |
157 | xen_hvm_resume_frames = alloc_xen_mmio(PAGE_SIZE * max_nr_gframes); | 158 | grant_frames = alloc_xen_mmio(PAGE_SIZE * max_nr_gframes); |
159 | if (gnttab_setup_auto_xlat_frames(grant_frames)) | ||
160 | goto out; | ||
158 | ret = gnttab_init(); | 161 | ret = gnttab_init(); |
159 | if (ret) | 162 | if (ret) |
160 | goto out; | 163 | goto grant_out; |
161 | xenbus_probe(NULL); | 164 | xenbus_probe(NULL); |
162 | return 0; | 165 | return 0; |
163 | 166 | grant_out: | |
167 | gnttab_free_auto_xlat_frames(); | ||
164 | out: | 168 | out: |
165 | pci_release_region(pdev, 0); | 169 | pci_release_region(pdev, 0); |
166 | mem_out: | 170 | mem_out: |
diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h index 694dcaf266e6..5acb1e4ac0d3 100644 --- a/include/xen/grant_table.h +++ b/include/xen/grant_table.h | |||
@@ -178,8 +178,15 @@ int arch_gnttab_map_status(uint64_t *frames, unsigned long nr_gframes, | |||
178 | grant_status_t **__shared); | 178 | grant_status_t **__shared); |
179 | void arch_gnttab_unmap(void *shared, unsigned long nr_gframes); | 179 | void arch_gnttab_unmap(void *shared, unsigned long nr_gframes); |
180 | 180 | ||
181 | extern unsigned long xen_hvm_resume_frames; | 181 | struct grant_frames { |
182 | xen_pfn_t *pfn; | ||
183 | unsigned int count; | ||
184 | void *vaddr; | ||
185 | }; | ||
186 | extern struct grant_frames xen_auto_xlat_grant_frames; | ||
182 | unsigned int gnttab_max_grant_frames(void); | 187 | unsigned int gnttab_max_grant_frames(void); |
188 | int gnttab_setup_auto_xlat_frames(unsigned long addr); | ||
189 | void gnttab_free_auto_xlat_frames(void); | ||
183 | 190 | ||
184 | #define gnttab_map_vaddr(map) ((void *)(map.host_virt_addr)) | 191 | #define gnttab_map_vaddr(map) ((void *)(map.host_virt_addr)) |
185 | 192 | ||