aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2014-01-06 10:40:36 -0500
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2014-01-06 10:44:20 -0500
commitefaf30a3357872cf0fc7d555b1f9968ec71535d3 (patch)
tree3ce0f48234ccf2b173b88ae8682b7ac5eb6b7722
parent456847533b9ad18baa6685946a2f1e1fa9c05c34 (diff)
xen/grant: Implement an grant frame array struct (v3).
The 'xen_hvm_resume_frames' used to be an 'unsigned long' and contain the virtual address of the grants. That was OK for most architectures (PVHVM, ARM) were the grants are contiguous in memory. That however is not the case for PVH - in which case we will have to do a lookup for each virtual address for the PFN. Instead of doing that, lets make it a structure which will contain the array of PFNs, the virtual address and the count of said PFNs. Also provide a generic functions: gnttab_setup_auto_xlat_frames and gnttab_free_auto_xlat_frames to populate said structure with appropriate values for PVHVM and ARM. To round it off, change the name from 'xen_hvm_resume_frames' to a more descriptive one - 'xen_auto_xlat_grant_frames'. For PVH, in patch "xen/pvh: Piggyback on PVHVM for grant driver" we will populate the 'xen_auto_xlat_grant_frames' by ourselves. v2 moves the xen_remap in the gnttab_setup_auto_xlat_frames and also introduces xen_unmap for gnttab_free_auto_xlat_frames. Suggested-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> [v3: Based on top of 'asm/xen/page.h: remove redundant semicolon'] Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
-rw-r--r--arch/arm/include/asm/xen/page.h1
-rw-r--r--arch/arm/xen/enlighten.c9
-rw-r--r--arch/x86/include/asm/xen/page.h1
-rw-r--r--drivers/xen/grant-table.c58
-rw-r--r--drivers/xen/platform-pci.c10
-rw-r--r--include/xen/grant_table.h9
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);
227void make_lowmem_page_readwrite(void *vaddr); 227void 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;
65static int gnttab_free_count; 65static int gnttab_free_count;
66static grant_ref_t gnttab_free_head; 66static grant_ref_t gnttab_free_head;
67static DEFINE_SPINLOCK(gnttab_list_lock); 67static DEFINE_SPINLOCK(gnttab_list_lock);
68unsigned long xen_hvm_resume_frames; 68struct grant_frames xen_auto_xlat_grant_frames;
69EXPORT_SYMBOL_GPL(xen_hvm_resume_frames);
70 69
71static union { 70static 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}
839EXPORT_SYMBOL_GPL(gnttab_max_grant_frames); 838EXPORT_SYMBOL_GPL(gnttab_max_grant_frames);
840 839
840int 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}
870EXPORT_SYMBOL_GPL(gnttab_setup_auto_xlat_frames);
871
872void 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}
883EXPORT_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
843static inline void 887static 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 166grant_out:
167 gnttab_free_auto_xlat_frames();
164out: 168out:
165 pci_release_region(pdev, 0); 169 pci_release_region(pdev, 0);
166mem_out: 170mem_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);
179void arch_gnttab_unmap(void *shared, unsigned long nr_gframes); 179void arch_gnttab_unmap(void *shared, unsigned long nr_gframes);
180 180
181extern unsigned long xen_hvm_resume_frames; 181struct grant_frames {
182 xen_pfn_t *pfn;
183 unsigned int count;
184 void *vaddr;
185};
186extern struct grant_frames xen_auto_xlat_grant_frames;
182unsigned int gnttab_max_grant_frames(void); 187unsigned int gnttab_max_grant_frames(void);
188int gnttab_setup_auto_xlat_frames(unsigned long addr);
189void 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