diff options
author | Stefano Stabellini <stefano.stabellini@eu.citrix.com> | 2013-04-25 12:17:04 -0400 |
---|---|---|
committer | Stefano Stabellini <stefano.stabellini@eu.citrix.com> | 2013-04-25 12:46:07 -0400 |
commit | 9a9ab3cc00dc0c338e3ab96f75a0e1a3c1aa3c27 (patch) | |
tree | 7e0470408c32ddedc8d1f3e1b40784516eb7756b /arch/arm/xen | |
parent | ea0af61321347d7742714d3ebf30df418e6482e2 (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.c | 48 |
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; | |||
32 | struct shared_info *HYPERVISOR_shared_info = (void *)&xen_dummy_shared_info; | 33 | struct shared_info *HYPERVISOR_shared_info = (void *)&xen_dummy_shared_info; |
33 | 34 | ||
34 | DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu); | 35 | DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu); |
36 | static 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" */ |
37 | unsigned long xen_released_pages; | 39 | unsigned long xen_released_pages; |
@@ -148,6 +150,29 @@ int xen_unmap_domain_mfn_range(struct vm_area_struct *vma, | |||
148 | } | 150 | } |
149 | EXPORT_SYMBOL_GPL(xen_unmap_domain_mfn_range); | 151 | EXPORT_SYMBOL_GPL(xen_unmap_domain_mfn_range); |
150 | 152 | ||
153 | static 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 | ||
265 | static __init void xen_percpu_enable_events(void *unused) | ||
266 | { | ||
267 | enable_percpu_irq(xen_events_irq, 0); | ||
268 | } | ||
269 | |||
234 | static int __init xen_init_events(void) | 270 | static 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 | } |