aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/xen
diff options
context:
space:
mode:
authorStefano Stabellini <stefano.stabellini@eu.citrix.com>2013-04-25 12:17:04 -0400
committerStefano Stabellini <stefano.stabellini@eu.citrix.com>2013-04-25 12:46:07 -0400
commit9a9ab3cc00dc0c338e3ab96f75a0e1a3c1aa3c27 (patch)
tree7e0470408c32ddedc8d1f3e1b40784516eb7756b /arch/arm/xen
parentea0af61321347d7742714d3ebf30df418e6482e2 (diff)
xen/arm: SMP support
Map vcpu_info using VCPUOP_register_vcpu_info on all the online vcpus, make sure the allocated struct doesn't cross a page boundary. Call enable_percpu_irq on every cpu. Changes in v5: - allocate xen_vcpu_info dynamically, aligning it to the size of the struct; - use VCPUOP_register_vcpu_info on cpu0 too. Changed in v2: - move the percpu variable argument fix to a separate patch; - remove unused variable. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Diffstat (limited to 'arch/arm/xen')
-rw-r--r--arch/arm/xen/enlighten.c48
1 files changed, 42 insertions, 6 deletions
diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c
index 82d5e63cb03b..6c87d116df63 100644
--- a/arch/arm/xen/enlighten.c
+++ b/arch/arm/xen/enlighten.c
@@ -2,6 +2,7 @@
2#include <xen/events.h> 2#include <xen/events.h>
3#include <xen/grant_table.h> 3#include <xen/grant_table.h>
4#include <xen/hvm.h> 4#include <xen/hvm.h>
5#include <xen/interface/vcpu.h>
5#include <xen/interface/xen.h> 6#include <xen/interface/xen.h>
6#include <xen/interface/memory.h> 7#include <xen/interface/memory.h>
7#include <xen/interface/hvm/params.h> 8#include <xen/interface/hvm/params.h>
@@ -32,6 +33,7 @@ struct shared_info xen_dummy_shared_info;
32struct shared_info *HYPERVISOR_shared_info = (void *)&xen_dummy_shared_info; 33struct shared_info *HYPERVISOR_shared_info = (void *)&xen_dummy_shared_info;
33 34
34DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu); 35DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu);
36static struct vcpu_info __percpu *xen_vcpu_info;
35 37
36/* These are unused until we support booting "pre-ballooned" */ 38/* These are unused until we support booting "pre-ballooned" */
37unsigned long xen_released_pages; 39unsigned long xen_released_pages;
@@ -148,6 +150,29 @@ int xen_unmap_domain_mfn_range(struct vm_area_struct *vma,
148} 150}
149EXPORT_SYMBOL_GPL(xen_unmap_domain_mfn_range); 151EXPORT_SYMBOL_GPL(xen_unmap_domain_mfn_range);
150 152
153static int __init xen_secondary_init(unsigned int cpu)
154{
155 struct vcpu_register_vcpu_info info;
156 struct vcpu_info *vcpup;
157 int err;
158
159 pr_info("Xen: initializing cpu%d\n", cpu);
160 vcpup = per_cpu_ptr(xen_vcpu_info, cpu);
161
162 info.mfn = __pa(vcpup) >> PAGE_SHIFT;
163 info.offset = offset_in_page(vcpup);
164
165 err = HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_info, cpu, &info);
166 if (err) {
167 pr_debug("register_vcpu_info failed: err=%d\n", err);
168 } else {
169 /* This cpu is using the registered vcpu info, even if
170 later ones fail to. */
171 per_cpu(xen_vcpu, cpu) = vcpup;
172 }
173 return 0;
174}
175
151/* 176/*
152 * see Documentation/devicetree/bindings/arm/xen.txt for the 177 * see Documentation/devicetree/bindings/arm/xen.txt for the
153 * documentation of the Xen Device Tree format. 178 * documentation of the Xen Device Tree format.
@@ -163,6 +188,7 @@ static int __init xen_guest_init(void)
163 const char *version = NULL; 188 const char *version = NULL;
164 const char *xen_prefix = "xen,xen-"; 189 const char *xen_prefix = "xen,xen-";
165 struct resource res; 190 struct resource res;
191 int i;
166 192
167 node = of_find_compatible_node(NULL, NULL, "xen,xen"); 193 node = of_find_compatible_node(NULL, NULL, "xen,xen");
168 if (!node) { 194 if (!node) {
@@ -209,13 +235,18 @@ static int __init xen_guest_init(void)
209 235
210 /* xen_vcpu is a pointer to the vcpu_info struct in the shared_info 236 /* xen_vcpu is a pointer to the vcpu_info struct in the shared_info
211 * page, we use it in the event channel upcall and in some pvclock 237 * page, we use it in the event channel upcall and in some pvclock
212 * related functions. We don't need the vcpu_info placement 238 * related functions.
213 * optimizations because we don't use any pv_mmu or pv_irq op on
214 * HVM.
215 * The shared info contains exactly 1 CPU (the boot CPU). The guest 239 * The shared info contains exactly 1 CPU (the boot CPU). The guest
216 * is required to use VCPUOP_register_vcpu_info to place vcpu info 240 * is required to use VCPUOP_register_vcpu_info to place vcpu info
217 * for secondary CPUs as they are brought up. */ 241 * for secondary CPUs as they are brought up.
218 per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0]; 242 * For uniformity we use VCPUOP_register_vcpu_info even on cpu0.
243 */
244 xen_vcpu_info = __alloc_percpu(sizeof(struct vcpu_info),
245 sizeof(struct vcpu_info));
246 if (xen_vcpu_info == NULL)
247 return -ENOMEM;
248 for_each_online_cpu(i)
249 xen_secondary_init(i);
219 250
220 gnttab_init(); 251 gnttab_init();
221 if (!xen_initial_domain()) 252 if (!xen_initial_domain())
@@ -231,6 +262,11 @@ static irqreturn_t xen_arm_callback(int irq, void *arg)
231 return IRQ_HANDLED; 262 return IRQ_HANDLED;
232} 263}
233 264
265static __init void xen_percpu_enable_events(void *unused)
266{
267 enable_percpu_irq(xen_events_irq, 0);
268}
269
234static int __init xen_init_events(void) 270static int __init xen_init_events(void)
235{ 271{
236 if (!xen_domain() || xen_events_irq < 0) 272 if (!xen_domain() || xen_events_irq < 0)
@@ -244,7 +280,7 @@ static int __init xen_init_events(void)
244 return -EINVAL; 280 return -EINVAL;
245 } 281 }
246 282
247 enable_percpu_irq(xen_events_irq, 0); 283 on_each_cpu(xen_percpu_enable_events, NULL, 0);
248 284
249 return 0; 285 return 0;
250} 286}