From 9dd4b2944c46e1fdbd0a516c221c8a2670cbf005 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 29 Aug 2013 07:43:52 -0500 Subject: ARM: xen: only set pm function ptrs for Xen guests xen_pm_init was unconditionally setting pm_power_off and arm_pm_restart function pointers. This breaks multi-platform kernels. Make this conditional on running as a Xen guest and make it a late_initcall to ensure it is setup after platform code for Dom0. Signed-off-by: Rob Herring Signed-off-by: Stefano Stabellini CC: stable@vger.kernel.org --- arch/arm/xen/enlighten.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c index c9770ba5c7df..e70ce04e9dad 100644 --- a/arch/arm/xen/enlighten.c +++ b/arch/arm/xen/enlighten.c @@ -272,12 +272,15 @@ core_initcall(xen_guest_init); static int __init xen_pm_init(void) { + if (!xen_domain()) + return -ENODEV; + pm_power_off = xen_power_off; arm_pm_restart = xen_restart; return 0; } -subsys_initcall(xen_pm_init); +late_initcall(xen_pm_init); static irqreturn_t xen_arm_callback(int irq, void *arg) { -- cgit v1.2.3-59-g8ed1b From d7f8f48d1eb3186b1b80b2ed9a7adab191f753e9 Mon Sep 17 00:00:00 2001 From: Boris Ostrovsky Date: Mon, 9 Sep 2013 10:44:26 +0000 Subject: xen/p2m: Don't call get_balloon_scratch_page() twice, keep interrupts disabled for multicalls m2p_remove_override() calls get_balloon_scratch_page() in MULTI_update_va_mapping() even though it already has pointer to this page from the earlier call (in scratch_page). This second call doesn't have a matching put_balloon_scratch_page() thus not restoring preempt count back. (Also, there is no put_balloon_scratch_page() in the error path.) In addition, the second multicall uses __xen_mc_entry() which does not disable interrupts. Rearrange xen_mc_* calls to keep interrupts off while performing multicalls. This commit fixes a regression introduced by: commit ee0726407feaf504dff304fb603652fb2d778b42 Author: Stefano Stabellini Date: Tue Jul 23 17:23:54 2013 +0000 xen/m2p: use GNTTABOP_unmap_and_replace to reinstate the original mapping Signed-off-by: Boris Ostrovsky Reviewed-by: Stefano Stabellini --- arch/x86/xen/p2m.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c index 0d4ec35895d4..8b901e8d782d 100644 --- a/arch/x86/xen/p2m.c +++ b/arch/x86/xen/p2m.c @@ -990,10 +990,13 @@ int m2p_remove_override(struct page *page, printk(KERN_WARNING "m2p_remove_override: " "pfn %lx mfn %lx, failed to modify kernel mappings", pfn, mfn); + put_balloon_scratch_page(); return -1; } - mcs = xen_mc_entry( + xen_mc_batch(); + + mcs = __xen_mc_entry( sizeof(struct gnttab_unmap_and_replace)); unmap_op = mcs.args; unmap_op->host_addr = kmap_op->host_addr; @@ -1003,12 +1006,11 @@ int m2p_remove_override(struct page *page, MULTI_grant_table_op(mcs.mc, GNTTABOP_unmap_and_replace, unmap_op, 1); - xen_mc_issue(PARAVIRT_LAZY_MMU); - mcs = __xen_mc_entry(0); MULTI_update_va_mapping(mcs.mc, scratch_page_address, - pfn_pte(page_to_pfn(get_balloon_scratch_page()), + pfn_pte(page_to_pfn(scratch_page), PAGE_KERNEL_RO), 0); + xen_mc_issue(PARAVIRT_LAZY_MMU); kmap_op->host_addr = 0; -- cgit v1.2.3-59-g8ed1b From e1a9c16b303725ac900fee2a3ec4dbe2c2f846ab Mon Sep 17 00:00:00 2001 From: Julien Grall Date: Mon, 9 Sep 2013 11:35:26 +0000 Subject: xen/arm: disable cpuidle and cpufreq when linux is running as dom0 When linux is running as dom0, Xen doesn't show the physical cpu but a virtual CPU. On some ARM SOC (for instance the exynos 5250), linux registers callbacks for cpuidle and cpufreq. When these callbacks are called, they will modify directly the physical cpu not the virtual one. It can impact the whole board instead of only dom0. Signed-off-by: Julien Grall Signed-off-by: Stefano Stabellini Reviewed-by: Konrad Rzeszutek Wilk --- arch/arm/xen/enlighten.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'arch') diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c index e70ce04e9dad..79b317a5e480 100644 --- a/arch/arm/xen/enlighten.c +++ b/arch/arm/xen/enlighten.c @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include @@ -266,6 +268,13 @@ static int __init xen_guest_init(void) if (!xen_initial_domain()) xenbus_probe(NULL); + /* + * Making sure board specific code will not set up ops for + * cpu idle and cpu freq. + */ + disable_cpuidle(); + disable_cpufreq(); + return 0; } core_initcall(xen_guest_init); -- cgit v1.2.3-59-g8ed1b From 1fb3a8b2cfb278f139d9ff7ca5fe06a65de64494 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Tue, 13 Aug 2013 11:47:21 -0400 Subject: xen/spinlock: Fix locking path engaging too soon under PVHVM. The xen_lock_spinning has a check for the kicker interrupts and if it is not initialized it will spin normally (not enter the slowpath). But for PVHVM case we would initialize the kicker interrupt before the CPU came online. This meant that if the booting CPU used a spinlock and went in the slowpath - it would enter the slowpath and block forever. The forever part because during bootup: the spinlock would be taken _before_ the CPU sets itself to be online (more on this further), and we enter to poll on the event channel forever. The bootup CPU (see commit fc78d343fa74514f6fd117b5ef4cd27e4ac30236 "xen/smp: initialize IPI vectors before marking CPU online" for details) and the CPU that started the bootup consult the cpu_online_mask to determine whether the booting CPU should get an IPI. The booting CPU has to set itself in this mask via: set_cpu_online(smp_processor_id(), true); However, if the spinlock is taken before this (and it is) and it polls on an event channel - it will never be woken up as the kernel will never send an IPI to an offline CPU. Note that the PVHVM logic in sending IPIs is using the HVM path which has numerous checks using the cpu_online_mask and cpu_active_mask. See above mention git commit for details. Signed-off-by: Konrad Rzeszutek Wilk Reviewed-by: David Vrabel --- arch/x86/xen/enlighten.c | 1 - arch/x86/xen/smp.c | 9 +++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 15939e872db2..f091c80974c4 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1692,7 +1692,6 @@ static int xen_hvm_cpu_notify(struct notifier_block *self, unsigned long action, case CPU_UP_PREPARE: xen_vcpu_setup(cpu); if (xen_have_vector_callback) { - xen_init_lock_cpu(cpu); if (xen_feature(XENFEAT_hvm_safe_pvclock)) xen_setup_timer(cpu); } diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 9235842cd76a..c21b825ed056 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -709,6 +709,15 @@ static int xen_hvm_cpu_up(unsigned int cpu, struct task_struct *tidle) WARN_ON(rc); if (!rc) rc = native_cpu_up(cpu, tidle); + + /* + * We must initialize the slowpath CPU kicker _after_ the native + * path has executed. If we initialized it before none of the + * unlocker IPI kicks would reach the booting CPU as the booting + * CPU had not set itself 'online' in cpu_online_mask. That mask + * is checked when IPIs are sent (on HVM at least). + */ + xen_init_lock_cpu(cpu); return rc; } -- cgit v1.2.3-59-g8ed1b From 6055aaf87dc835ffdb238f6098110d36b40e3ad3 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Tue, 13 Aug 2013 11:53:35 -0400 Subject: xen/spinlock: We don't need the old structure anymore As we are using the generic ticketlock structs and these old structures are not needed anymore. Signed-off-by: Konrad Rzeszutek Wilk Reviewed-by: David Vrabel --- arch/x86/xen/spinlock.c | 18 ------------------ 1 file changed, 18 deletions(-) (limited to 'arch') diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c index 0438b9324a72..71db82ce08c6 100644 --- a/arch/x86/xen/spinlock.c +++ b/arch/x86/xen/spinlock.c @@ -81,7 +81,6 @@ static inline void spin_time_accum_blocked(u64 start) spinlock_stats.time_blocked += delta; } #else /* !CONFIG_XEN_DEBUG_FS */ -#define TIMEOUT (1 << 10) static inline void add_stats(enum xen_contention_stat var, u32 val) { } @@ -96,23 +95,6 @@ static inline void spin_time_accum_blocked(u64 start) } #endif /* CONFIG_XEN_DEBUG_FS */ -/* - * Size struct xen_spinlock so it's the same as arch_spinlock_t. - */ -#if NR_CPUS < 256 -typedef u8 xen_spinners_t; -# define inc_spinners(xl) \ - asm(LOCK_PREFIX " incb %0" : "+m" ((xl)->spinners) : : "memory"); -# define dec_spinners(xl) \ - asm(LOCK_PREFIX " decb %0" : "+m" ((xl)->spinners) : : "memory"); -#else -typedef u16 xen_spinners_t; -# define inc_spinners(xl) \ - asm(LOCK_PREFIX " incw %0" : "+m" ((xl)->spinners) : : "memory"); -# define dec_spinners(xl) \ - asm(LOCK_PREFIX " decw %0" : "+m" ((xl)->spinners) : : "memory"); -#endif - struct xen_lock_waiting { struct arch_spinlock *lock; __ticket_t want; -- cgit v1.2.3-59-g8ed1b From 26a799952737de20626e8c5c51b24534f1c90536 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Fri, 16 Aug 2013 14:39:56 -0400 Subject: xen/smp: Update pv_lock_ops functions before alternative code starts under PVHVM Before this patch we would patch all of the pv_lock_ops sites using alternative assembler. Then later in the bootup cycle change the unlock_kick and lock_spinning to the Xen specific - without re patching. That meant that for the core of the kernel we would be running with the baremetal version of unlock_kick and lock_spinning while for modules we would have the proper Xen specific slowpaths. As most of the module uses some API from the core kernel that ended up with slowpath lockers waiting forever to be kicked (b/c they would be using the Xen specific slowpath logic). And the kick never came b/c the unlock path that was taken was the baremetal one. On PV we do not have the problem as we initialise before the alternative code kicks in. The fix is to make the updating of the pv_lock_ops function be done before the alternative code starts patching. Note that this patch fixes issues discovered by commit f10cd522c5fbfec9ae3cc01967868c9c2401ed23. ("xen: disable PV spinlocks on HVM") wherein it mentioned PV spinlocks cannot possibly work with the current code because they are enabled after pvops patching has already been done, and because PV spinlocks use a different data structure than native spinlocks so we cannot switch between them dynamically. The first problem is solved by this patch. The second problem has been solved by commit 816434ec4a674fcdb3c2221a6dffdc8f34020550 (Merge branch 'x86-spinlocks-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip) P.S. There is still the commit 70dd4998cb85f0ecd6ac892cc7232abefa432efb (xen/spinlock: Disable IRQ spinlock (PV) allocation on PVHVM) to revert but that can be done later after all other bugs have been fixed. Signed-off-by: Konrad Rzeszutek Wilk Reviewed-by: David Vrabel --- arch/x86/xen/smp.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index c21b825ed056..d1e4777b4e75 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -273,12 +273,20 @@ static void __init xen_smp_prepare_boot_cpu(void) BUG_ON(smp_processor_id() != 0); native_smp_prepare_boot_cpu(); - /* We've switched to the "real" per-cpu gdt, so make sure the - old memory can be recycled */ - make_lowmem_page_readwrite(xen_initial_gdt); + if (xen_pv_domain()) { + /* We've switched to the "real" per-cpu gdt, so make sure the + old memory can be recycled */ + make_lowmem_page_readwrite(xen_initial_gdt); - xen_filter_cpu_maps(); - xen_setup_vcpu_info_placement(); + xen_filter_cpu_maps(); + xen_setup_vcpu_info_placement(); + } + /* + * The alternative logic (which patches the unlock/lock) runs before + * the smp bootup up code is activated. Hence we need to set this up + * the core kernel is being patched. Otherwise we will have only + * modules patched but not core code. + */ xen_init_spinlocks(); } @@ -737,4 +745,5 @@ void __init xen_hvm_smp_init(void) smp_ops.cpu_die = xen_hvm_cpu_die; smp_ops.send_call_func_ipi = xen_smp_send_call_function_ipi; smp_ops.send_call_func_single_ipi = xen_smp_send_call_function_single_ipi; + smp_ops.smp_prepare_boot_cpu = xen_smp_prepare_boot_cpu; } -- cgit v1.2.3-59-g8ed1b From 3310bbedac497b793b96184e1b9b5da4f747d53a Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Mon, 26 Aug 2013 14:28:06 -0400 Subject: xen/spinlock: Don't setup xen spinlock IPI kicker if disabled. There is no need to setup this kicker IPI if we are never going to use the paravirtualized ticketlock mechanism. Signed-off-by: Konrad Rzeszutek Wilk Reviewed-by: David Vrabel --- arch/x86/xen/spinlock.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c index 71db82ce08c6..e1bff87766be 100644 --- a/arch/x86/xen/spinlock.c +++ b/arch/x86/xen/spinlock.c @@ -105,6 +105,7 @@ static DEFINE_PER_CPU(char *, irq_name); static DEFINE_PER_CPU(struct xen_lock_waiting, lock_waiting); static cpumask_t waiting_cpus; +static bool xen_pvspin __initdata = true; static void xen_lock_spinning(struct arch_spinlock *lock, __ticket_t want) { int irq = __this_cpu_read(lock_kicker_irq); @@ -223,6 +224,9 @@ void xen_init_lock_cpu(int cpu) int irq; char *name; + if (!xen_pvspin) + return; + WARN(per_cpu(lock_kicker_irq, cpu) >= 0, "spinlock on CPU%d exists on IRQ%d!\n", cpu, per_cpu(lock_kicker_irq, cpu)); @@ -259,13 +263,15 @@ void xen_uninit_lock_cpu(int cpu) if (xen_hvm_domain()) return; + if (!xen_pvspin) + return; + unbind_from_irqhandler(per_cpu(lock_kicker_irq, cpu), NULL); per_cpu(lock_kicker_irq, cpu) = -1; kfree(per_cpu(irq_name, cpu)); per_cpu(irq_name, cpu) = NULL; } -static bool xen_pvspin __initdata = true; void __init xen_init_spinlocks(void) { @@ -305,6 +311,9 @@ static int __init xen_spinlock_debugfs(void) if (d_xen == NULL) return -ENOMEM; + if (!xen_pvspin) + return 0; + d_spin_debug = debugfs_create_dir("spinlocks", d_xen); debugfs_create_u8("zero_stats", 0644, d_spin_debug, &zero_stats); -- cgit v1.2.3-59-g8ed1b From fb78e58c275599a961557bca201dd897565833ca Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Mon, 26 Aug 2013 14:28:50 -0400 Subject: Revert "xen/spinlock: Disable IRQ spinlock (PV) allocation on PVHVM" This reverts commit 70dd4998cb85f0ecd6ac892cc7232abefa432efb. Now that the bugs have been resolved we can re-enable the PV ticketlock implementation under PVHVM Xen guests. Signed-off-by: Konrad Rzeszutek Wilk Reviewed-by: David Vrabel --- arch/x86/xen/spinlock.c | 20 -------------------- 1 file changed, 20 deletions(-) (limited to 'arch') diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c index e1bff87766be..b3c1ee8f0993 100644 --- a/arch/x86/xen/spinlock.c +++ b/arch/x86/xen/spinlock.c @@ -230,13 +230,6 @@ void xen_init_lock_cpu(int cpu) WARN(per_cpu(lock_kicker_irq, cpu) >= 0, "spinlock on CPU%d exists on IRQ%d!\n", cpu, per_cpu(lock_kicker_irq, cpu)); - /* - * See git commit f10cd522c5fbfec9ae3cc01967868c9c2401ed23 - * (xen: disable PV spinlocks on HVM) - */ - if (xen_hvm_domain()) - return; - name = kasprintf(GFP_KERNEL, "spinlock%d", cpu); irq = bind_ipi_to_irqhandler(XEN_SPIN_UNLOCK_VECTOR, cpu, @@ -256,13 +249,6 @@ void xen_init_lock_cpu(int cpu) void xen_uninit_lock_cpu(int cpu) { - /* - * See git commit f10cd522c5fbfec9ae3cc01967868c9c2401ed23 - * (xen: disable PV spinlocks on HVM) - */ - if (xen_hvm_domain()) - return; - if (!xen_pvspin) return; @@ -275,12 +261,6 @@ void xen_uninit_lock_cpu(int cpu) void __init xen_init_spinlocks(void) { - /* - * See git commit f10cd522c5fbfec9ae3cc01967868c9c2401ed23 - * (xen: disable PV spinlocks on HVM) - */ - if (xen_hvm_domain()) - return; if (!xen_pvspin) { printk(KERN_DEBUG "xen: PV spinlocks disabled\n"); -- cgit v1.2.3-59-g8ed1b From c3b7cb1fd8c1513be99fb3cfb7f39c5116d80dac Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Mon, 9 Sep 2013 13:08:49 -0400 Subject: xen/spinlock: Don't use __initdate for xen_pv_spin As we get compile warnings about .init.data being used by non-init functions. Reported-by: kbuild test robot Signed-off-by: Konrad Rzeszutek Wilk --- arch/x86/xen/spinlock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c index b3c1ee8f0993..253f63fceea1 100644 --- a/arch/x86/xen/spinlock.c +++ b/arch/x86/xen/spinlock.c @@ -105,7 +105,7 @@ static DEFINE_PER_CPU(char *, irq_name); static DEFINE_PER_CPU(struct xen_lock_waiting, lock_waiting); static cpumask_t waiting_cpus; -static bool xen_pvspin __initdata = true; +static bool xen_pvspin = true; static void xen_lock_spinning(struct arch_spinlock *lock, __ticket_t want) { int irq = __this_cpu_read(lock_kicker_irq); -- cgit v1.2.3-59-g8ed1b