diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-07 18:11:43 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-07 18:11:43 -0400 |
commit | d75e2f902318cc20f3218e6823fe5463a8126bde (patch) | |
tree | a08a87bab72df38d2f7f865bcb59cc43f608245b /arch/arm | |
parent | de9c9f86be0dc3495de98dc65c80abe6e7c7d643 (diff) | |
parent | 9bc25a1d5f95f97e9e378620a46e954d3f842641 (diff) |
Merge tag '3.9-rc3-smp-6-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/sstabellini/xen
Pull ARM Xen SMP updates from Stefano Stabellini:
"This contains a bunch of Xen/ARM specific changes, including some
fixes, SMP support for Xen on ARM, and moving the xenvm machine from
mach-vexpress to mach-virt.
The non-Xen files that are touched are arch/arm/Kconfig, to select
ARM_PSCI on XEN, and arch/arm/boot/dts/Makefile, to build the xenvm
DTB if CONFIG_ARCH_VIRT.
Highlights:
- Move xenvm to mach-virt.
- Implement SMP support in Xen on ARM.
- Add support for machine reboot and power off via Xen hypercalls"
* tag '3.9-rc3-smp-6-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/sstabellini/xen:
xen/arm: remove duplicated include from enlighten.c
xen/arm: use sched_op hypercalls for machine reboot and power off
xenvm: add a simple PSCI node and a second cpu
xen/arm: XEN selects ARM_PSCI
xen: move the xenvm machine to mach-virt
xen/arm: SMP support
xen/arm: implement HYPERVISOR_vcpu_op
xen/arm: actually pass a non-NULL percpu pointer to request_percpu_irq
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/Kconfig | 1 | ||||
-rw-r--r-- | arch/arm/boot/dts/Makefile | 4 | ||||
-rw-r--r-- | arch/arm/boot/dts/xenvm-4.2.dts | 13 | ||||
-rw-r--r-- | arch/arm/include/asm/xen/hypercall.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-vexpress/v2m.c | 1 | ||||
-rw-r--r-- | arch/arm/mach-virt/virt.c | 1 | ||||
-rw-r--r-- | arch/arm/xen/enlighten.c | 74 | ||||
-rw-r--r-- | arch/arm/xen/hypercall.S | 1 |
8 files changed, 86 insertions, 10 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 34ef016626ff..aa71a2321040 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -1794,6 +1794,7 @@ config XEN | |||
1794 | depends on ARM && AEABI && OF | 1794 | depends on ARM && AEABI && OF |
1795 | depends on CPU_V7 && !CPU_V6 | 1795 | depends on CPU_V7 && !CPU_V6 |
1796 | depends on !GENERIC_ATOMIC64 | 1796 | depends on !GENERIC_ATOMIC64 |
1797 | select ARM_PSCI | ||
1797 | help | 1798 | help |
1798 | Say Y if you want to run Linux in a Virtual Machine on Xen on ARM. | 1799 | Say Y if you want to run Linux in a Virtual Machine on Xen on ARM. |
1799 | 1800 | ||
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 8562af4fe8fd..b9f7121e6ecf 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile | |||
@@ -200,8 +200,8 @@ dtb-$(CONFIG_ARCH_VERSATILE) += versatile-ab.dtb \ | |||
200 | dtb-$(CONFIG_ARCH_VEXPRESS) += vexpress-v2p-ca5s.dtb \ | 200 | dtb-$(CONFIG_ARCH_VEXPRESS) += vexpress-v2p-ca5s.dtb \ |
201 | vexpress-v2p-ca9.dtb \ | 201 | vexpress-v2p-ca9.dtb \ |
202 | vexpress-v2p-ca15-tc1.dtb \ | 202 | vexpress-v2p-ca15-tc1.dtb \ |
203 | vexpress-v2p-ca15_a7.dtb \ | 203 | vexpress-v2p-ca15_a7.dtb |
204 | xenvm-4.2.dtb | 204 | dtb-$(CONFIG_ARCH_VIRT) += xenvm-4.2.dtb |
205 | dtb-$(CONFIG_ARCH_VT8500) += vt8500-bv07.dtb \ | 205 | dtb-$(CONFIG_ARCH_VT8500) += vt8500-bv07.dtb \ |
206 | wm8505-ref.dtb \ | 206 | wm8505-ref.dtb \ |
207 | wm8650-mid.dtb \ | 207 | wm8650-mid.dtb \ |
diff --git a/arch/arm/boot/dts/xenvm-4.2.dts b/arch/arm/boot/dts/xenvm-4.2.dts index ec3f9528e180..336915151398 100644 --- a/arch/arm/boot/dts/xenvm-4.2.dts +++ b/arch/arm/boot/dts/xenvm-4.2.dts | |||
@@ -29,6 +29,19 @@ | |||
29 | compatible = "arm,cortex-a15"; | 29 | compatible = "arm,cortex-a15"; |
30 | reg = <0>; | 30 | reg = <0>; |
31 | }; | 31 | }; |
32 | |||
33 | cpu@1 { | ||
34 | device_type = "cpu"; | ||
35 | compatible = "arm,cortex-a15"; | ||
36 | reg = <1>; | ||
37 | }; | ||
38 | }; | ||
39 | |||
40 | psci { | ||
41 | compatible = "arm,psci"; | ||
42 | method = "hvc"; | ||
43 | cpu_off = <1>; | ||
44 | cpu_on = <2>; | ||
32 | }; | 45 | }; |
33 | 46 | ||
34 | memory@80000000 { | 47 | memory@80000000 { |
diff --git a/arch/arm/include/asm/xen/hypercall.h b/arch/arm/include/asm/xen/hypercall.h index 8a823253d775..799f42ecca63 100644 --- a/arch/arm/include/asm/xen/hypercall.h +++ b/arch/arm/include/asm/xen/hypercall.h | |||
@@ -46,6 +46,7 @@ int HYPERVISOR_event_channel_op(int cmd, void *arg); | |||
46 | unsigned long HYPERVISOR_hvm_op(int op, void *arg); | 46 | unsigned long HYPERVISOR_hvm_op(int op, void *arg); |
47 | int HYPERVISOR_memory_op(unsigned int cmd, void *arg); | 47 | int HYPERVISOR_memory_op(unsigned int cmd, void *arg); |
48 | int HYPERVISOR_physdev_op(int cmd, void *arg); | 48 | int HYPERVISOR_physdev_op(int cmd, void *arg); |
49 | int HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args); | ||
49 | 50 | ||
50 | static inline void | 51 | static inline void |
51 | MULTI_update_va_mapping(struct multicall_entry *mcl, unsigned long va, | 52 | MULTI_update_va_mapping(struct multicall_entry *mcl, unsigned long va, |
diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c index b6083bb1eb8c..8802030df98d 100644 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c | |||
@@ -450,7 +450,6 @@ static void __init v2m_dt_init(void) | |||
450 | 450 | ||
451 | static const char * const v2m_dt_match[] __initconst = { | 451 | static const char * const v2m_dt_match[] __initconst = { |
452 | "arm,vexpress", | 452 | "arm,vexpress", |
453 | "xen,xenvm", | ||
454 | NULL, | 453 | NULL, |
455 | }; | 454 | }; |
456 | 455 | ||
diff --git a/arch/arm/mach-virt/virt.c b/arch/arm/mach-virt/virt.c index adc0945255ae..061f283f579e 100644 --- a/arch/arm/mach-virt/virt.c +++ b/arch/arm/mach-virt/virt.c | |||
@@ -32,6 +32,7 @@ static void __init virt_init(void) | |||
32 | 32 | ||
33 | static const char *virt_dt_match[] = { | 33 | static const char *virt_dt_match[] = { |
34 | "linux,dummy-virt", | 34 | "linux,dummy-virt", |
35 | "xen,xenvm", | ||
35 | NULL | 36 | NULL |
36 | }; | 37 | }; |
37 | 38 | ||
diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c index 8dc0605a9ce9..d30042e39974 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> |
@@ -9,9 +10,11 @@ | |||
9 | #include <xen/platform_pci.h> | 10 | #include <xen/platform_pci.h> |
10 | #include <xen/xenbus.h> | 11 | #include <xen/xenbus.h> |
11 | #include <xen/page.h> | 12 | #include <xen/page.h> |
13 | #include <xen/interface/sched.h> | ||
12 | #include <xen/xen-ops.h> | 14 | #include <xen/xen-ops.h> |
13 | #include <asm/xen/hypervisor.h> | 15 | #include <asm/xen/hypervisor.h> |
14 | #include <asm/xen/hypercall.h> | 16 | #include <asm/xen/hypercall.h> |
17 | #include <asm/system_misc.h> | ||
15 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
16 | #include <linux/irqreturn.h> | 19 | #include <linux/irqreturn.h> |
17 | #include <linux/module.h> | 20 | #include <linux/module.h> |
@@ -32,6 +35,7 @@ struct shared_info xen_dummy_shared_info; | |||
32 | struct shared_info *HYPERVISOR_shared_info = (void *)&xen_dummy_shared_info; | 35 | struct shared_info *HYPERVISOR_shared_info = (void *)&xen_dummy_shared_info; |
33 | 36 | ||
34 | DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu); | 37 | DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu); |
38 | static struct vcpu_info __percpu *xen_vcpu_info; | ||
35 | 39 | ||
36 | /* These are unused until we support booting "pre-ballooned" */ | 40 | /* These are unused until we support booting "pre-ballooned" */ |
37 | unsigned long xen_released_pages; | 41 | unsigned long xen_released_pages; |
@@ -148,6 +152,47 @@ int xen_unmap_domain_mfn_range(struct vm_area_struct *vma, | |||
148 | } | 152 | } |
149 | EXPORT_SYMBOL_GPL(xen_unmap_domain_mfn_range); | 153 | EXPORT_SYMBOL_GPL(xen_unmap_domain_mfn_range); |
150 | 154 | ||
155 | static int __init xen_secondary_init(unsigned int cpu) | ||
156 | { | ||
157 | struct vcpu_register_vcpu_info info; | ||
158 | struct vcpu_info *vcpup; | ||
159 | int err; | ||
160 | |||
161 | pr_info("Xen: initializing cpu%d\n", cpu); | ||
162 | vcpup = per_cpu_ptr(xen_vcpu_info, cpu); | ||
163 | |||
164 | info.mfn = __pa(vcpup) >> PAGE_SHIFT; | ||
165 | info.offset = offset_in_page(vcpup); | ||
166 | |||
167 | err = HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_info, cpu, &info); | ||
168 | if (err) { | ||
169 | pr_debug("register_vcpu_info failed: err=%d\n", err); | ||
170 | } else { | ||
171 | /* This cpu is using the registered vcpu info, even if | ||
172 | later ones fail to. */ | ||
173 | per_cpu(xen_vcpu, cpu) = vcpup; | ||
174 | } | ||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | static void xen_restart(char str, const char *cmd) | ||
179 | { | ||
180 | struct sched_shutdown r = { .reason = SHUTDOWN_reboot }; | ||
181 | int rc; | ||
182 | rc = HYPERVISOR_sched_op(SCHEDOP_shutdown, &r); | ||
183 | if (rc) | ||
184 | BUG(); | ||
185 | } | ||
186 | |||
187 | static void xen_power_off(void) | ||
188 | { | ||
189 | struct sched_shutdown r = { .reason = SHUTDOWN_poweroff }; | ||
190 | int rc; | ||
191 | rc = HYPERVISOR_sched_op(SCHEDOP_shutdown, &r); | ||
192 | if (rc) | ||
193 | BUG(); | ||
194 | } | ||
195 | |||
151 | /* | 196 | /* |
152 | * see Documentation/devicetree/bindings/arm/xen.txt for the | 197 | * see Documentation/devicetree/bindings/arm/xen.txt for the |
153 | * documentation of the Xen Device Tree format. | 198 | * documentation of the Xen Device Tree format. |
@@ -163,6 +208,7 @@ static int __init xen_guest_init(void) | |||
163 | const char *version = NULL; | 208 | const char *version = NULL; |
164 | const char *xen_prefix = "xen,xen-"; | 209 | const char *xen_prefix = "xen,xen-"; |
165 | struct resource res; | 210 | struct resource res; |
211 | int i; | ||
166 | 212 | ||
167 | node = of_find_compatible_node(NULL, NULL, "xen,xen"); | 213 | node = of_find_compatible_node(NULL, NULL, "xen,xen"); |
168 | if (!node) { | 214 | if (!node) { |
@@ -209,18 +255,26 @@ static int __init xen_guest_init(void) | |||
209 | 255 | ||
210 | /* xen_vcpu is a pointer to the vcpu_info struct in the shared_info | 256 | /* 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 | 257 | * page, we use it in the event channel upcall and in some pvclock |
212 | * related functions. We don't need the vcpu_info placement | 258 | * 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 | 259 | * 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 | 260 | * is required to use VCPUOP_register_vcpu_info to place vcpu info |
217 | * for secondary CPUs as they are brought up. */ | 261 | * for secondary CPUs as they are brought up. |
218 | per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0]; | 262 | * For uniformity we use VCPUOP_register_vcpu_info even on cpu0. |
263 | */ | ||
264 | xen_vcpu_info = __alloc_percpu(sizeof(struct vcpu_info), | ||
265 | sizeof(struct vcpu_info)); | ||
266 | if (xen_vcpu_info == NULL) | ||
267 | return -ENOMEM; | ||
268 | for_each_online_cpu(i) | ||
269 | xen_secondary_init(i); | ||
219 | 270 | ||
220 | gnttab_init(); | 271 | gnttab_init(); |
221 | if (!xen_initial_domain()) | 272 | if (!xen_initial_domain()) |
222 | xenbus_probe(NULL); | 273 | xenbus_probe(NULL); |
223 | 274 | ||
275 | pm_power_off = xen_power_off; | ||
276 | arm_pm_restart = xen_restart; | ||
277 | |||
224 | return 0; | 278 | return 0; |
225 | } | 279 | } |
226 | core_initcall(xen_guest_init); | 280 | core_initcall(xen_guest_init); |
@@ -231,6 +285,11 @@ static irqreturn_t xen_arm_callback(int irq, void *arg) | |||
231 | return IRQ_HANDLED; | 285 | return IRQ_HANDLED; |
232 | } | 286 | } |
233 | 287 | ||
288 | static __init void xen_percpu_enable_events(void *unused) | ||
289 | { | ||
290 | enable_percpu_irq(xen_events_irq, 0); | ||
291 | } | ||
292 | |||
234 | static int __init xen_init_events(void) | 293 | static int __init xen_init_events(void) |
235 | { | 294 | { |
236 | if (!xen_domain() || xen_events_irq < 0) | 295 | if (!xen_domain() || xen_events_irq < 0) |
@@ -239,12 +298,12 @@ static int __init xen_init_events(void) | |||
239 | xen_init_IRQ(); | 298 | xen_init_IRQ(); |
240 | 299 | ||
241 | if (request_percpu_irq(xen_events_irq, xen_arm_callback, | 300 | if (request_percpu_irq(xen_events_irq, xen_arm_callback, |
242 | "events", xen_vcpu)) { | 301 | "events", &xen_vcpu)) { |
243 | pr_err("Error requesting IRQ %d\n", xen_events_irq); | 302 | pr_err("Error requesting IRQ %d\n", xen_events_irq); |
244 | return -EINVAL; | 303 | return -EINVAL; |
245 | } | 304 | } |
246 | 305 | ||
247 | enable_percpu_irq(xen_events_irq, 0); | 306 | on_each_cpu(xen_percpu_enable_events, NULL, 0); |
248 | 307 | ||
249 | return 0; | 308 | return 0; |
250 | } | 309 | } |
@@ -259,4 +318,5 @@ EXPORT_SYMBOL_GPL(HYPERVISOR_sched_op); | |||
259 | EXPORT_SYMBOL_GPL(HYPERVISOR_hvm_op); | 318 | EXPORT_SYMBOL_GPL(HYPERVISOR_hvm_op); |
260 | EXPORT_SYMBOL_GPL(HYPERVISOR_memory_op); | 319 | EXPORT_SYMBOL_GPL(HYPERVISOR_memory_op); |
261 | EXPORT_SYMBOL_GPL(HYPERVISOR_physdev_op); | 320 | EXPORT_SYMBOL_GPL(HYPERVISOR_physdev_op); |
321 | EXPORT_SYMBOL_GPL(HYPERVISOR_vcpu_op); | ||
262 | EXPORT_SYMBOL_GPL(privcmd_call); | 322 | EXPORT_SYMBOL_GPL(privcmd_call); |
diff --git a/arch/arm/xen/hypercall.S b/arch/arm/xen/hypercall.S index 71f723984cbd..199cb2da7663 100644 --- a/arch/arm/xen/hypercall.S +++ b/arch/arm/xen/hypercall.S | |||
@@ -87,6 +87,7 @@ HYPERCALL2(event_channel_op); | |||
87 | HYPERCALL2(hvm_op); | 87 | HYPERCALL2(hvm_op); |
88 | HYPERCALL2(memory_op); | 88 | HYPERCALL2(memory_op); |
89 | HYPERCALL2(physdev_op); | 89 | HYPERCALL2(physdev_op); |
90 | HYPERCALL3(vcpu_op); | ||
90 | 91 | ||
91 | ENTRY(privcmd_call) | 92 | ENTRY(privcmd_call) |
92 | stmdb sp!, {r4} | 93 | stmdb sp!, {r4} |