From 5fc509bc2bd6dddd4107eaf90680cd76cfc2ffed Mon Sep 17 00:00:00 2001 From: Boris Ostrovsky Date: Wed, 3 Aug 2016 13:22:27 -0400 Subject: xen/x86: Move irq allocation from Xen smp_op.cpu_up() Commit ce0d3c0a6fb1 ("genirq: Revert sparse irq locking around __cpu_up() and move it to x86 for now") reverted irq locking introduced by commit a89941816726 ("hotplug: Prevent alloc/free of irq descriptors during cpu up/down") because of Xen allocating irqs in both of its cpu_up ops. We can move those allocations into CPU notifiers so that original patch can be reinstated. Signed-off-by: Boris Ostrovsky Signed-off-by: David Vrabel --- arch/x86/xen/enlighten.c | 61 +++++++++++++++++++++++++++++++++++++----------- arch/x86/xen/smp.c | 45 ++--------------------------------- arch/x86/xen/smp.h | 13 +++++++++++ 3 files changed, 63 insertions(+), 56 deletions(-) (limited to 'arch/x86') diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 8ffb089b19a5..c7f6b1f90efa 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -140,6 +140,8 @@ RESERVE_BRK(shared_info_page_brk, PAGE_SIZE); __read_mostly int xen_have_vector_callback; EXPORT_SYMBOL_GPL(xen_have_vector_callback); +static struct notifier_block xen_cpu_notifier; + /* * Point at some empty memory to start with. We map the real shared_info * page as soon as fixmap is up and running. @@ -1627,6 +1629,7 @@ asmlinkage __visible void __init xen_start_kernel(void) xen_initial_gdt = &per_cpu(gdt_page, 0); xen_smp_init(); + register_cpu_notifier(&xen_cpu_notifier); #ifdef CONFIG_ACPI_NUMA /* @@ -1820,21 +1823,53 @@ static void __init init_hvm_pv_info(void) xen_domain_type = XEN_HVM_DOMAIN; } -static int xen_hvm_cpu_notify(struct notifier_block *self, unsigned long action, - void *hcpu) +static int xen_cpu_notify(struct notifier_block *self, unsigned long action, + void *hcpu) { int cpu = (long)hcpu; + int rc; + switch (action) { case CPU_UP_PREPARE: - if (cpu_acpi_id(cpu) != U32_MAX) - per_cpu(xen_vcpu_id, cpu) = cpu_acpi_id(cpu); - else - per_cpu(xen_vcpu_id, cpu) = cpu; - xen_vcpu_setup(cpu); - if (xen_have_vector_callback) { - if (xen_feature(XENFEAT_hvm_safe_pvclock)) - xen_setup_timer(cpu); + if (xen_hvm_domain()) { + /* + * This can happen if CPU was offlined earlier and + * offlining timed out in common_cpu_die(). + */ + if (cpu_report_state(cpu) == CPU_DEAD_FROZEN) { + xen_smp_intr_free(cpu); + xen_uninit_lock_cpu(cpu); + } + + if (cpu_acpi_id(cpu) != U32_MAX) + per_cpu(xen_vcpu_id, cpu) = cpu_acpi_id(cpu); + else + per_cpu(xen_vcpu_id, cpu) = cpu; + xen_vcpu_setup(cpu); } + + if (xen_pv_domain() || + (xen_have_vector_callback && + xen_feature(XENFEAT_hvm_safe_pvclock))) + xen_setup_timer(cpu); + + rc = xen_smp_intr_init(cpu); + if (rc) { + WARN(1, "xen_smp_intr_init() for CPU %d failed: %d\n", + cpu, rc); + return NOTIFY_BAD; + } + + break; + case CPU_ONLINE: + xen_init_lock_cpu(cpu); + break; + case CPU_UP_CANCELED: + xen_smp_intr_free(cpu); + if (xen_pv_domain() || + (xen_have_vector_callback && + xen_feature(XENFEAT_hvm_safe_pvclock))) + xen_teardown_timer(cpu); break; default: break; @@ -1842,8 +1877,8 @@ static int xen_hvm_cpu_notify(struct notifier_block *self, unsigned long action, return NOTIFY_OK; } -static struct notifier_block xen_hvm_cpu_notifier = { - .notifier_call = xen_hvm_cpu_notify, +static struct notifier_block xen_cpu_notifier = { + .notifier_call = xen_cpu_notify, }; #ifdef CONFIG_KEXEC_CORE @@ -1875,7 +1910,7 @@ static void __init xen_hvm_guest_init(void) if (xen_feature(XENFEAT_hvm_callback_vector)) xen_have_vector_callback = 1; xen_hvm_smp_init(); - register_cpu_notifier(&xen_hvm_cpu_notifier); + register_cpu_notifier(&xen_cpu_notifier); xen_unplug_emulated_devices(); x86_init.irqs.intr_init = xen_init_IRQ; xen_hvm_init_time_ops(); diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 0b4d04c8ab4d..137afbbd0590 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -115,7 +115,7 @@ asmlinkage __visible void cpu_bringup_and_idle(int cpu) cpu_startup_entry(CPUHP_AP_ONLINE_IDLE); } -static void xen_smp_intr_free(unsigned int cpu) +void xen_smp_intr_free(unsigned int cpu) { if (per_cpu(xen_resched_irq, cpu).irq >= 0) { unbind_from_irqhandler(per_cpu(xen_resched_irq, cpu).irq, NULL); @@ -159,7 +159,7 @@ static void xen_smp_intr_free(unsigned int cpu) per_cpu(xen_pmu_irq, cpu).name = NULL; } }; -static int xen_smp_intr_init(unsigned int cpu) +int xen_smp_intr_init(unsigned int cpu) { int rc; char *resched_name, *callfunc_name, *debug_name, *pmu_name; @@ -475,8 +475,6 @@ static int xen_cpu_up(unsigned int cpu, struct task_struct *idle) common_cpu_up(cpu, idle); xen_setup_runstate_info(cpu); - xen_setup_timer(cpu); - xen_init_lock_cpu(cpu); /* * PV VCPUs are always successfully taken down (see 'while' loop @@ -495,10 +493,6 @@ static int xen_cpu_up(unsigned int cpu, struct task_struct *idle) xen_pmu_init(cpu); - rc = xen_smp_intr_init(cpu); - if (rc) - return rc; - rc = HYPERVISOR_vcpu_op(VCPUOP_up, xen_vcpu_nr(cpu), NULL); BUG_ON(rc); @@ -769,47 +763,12 @@ static void __init xen_hvm_smp_prepare_cpus(unsigned int max_cpus) xen_init_lock_cpu(0); } -static int xen_hvm_cpu_up(unsigned int cpu, struct task_struct *tidle) -{ - int rc; - - /* - * This can happen if CPU was offlined earlier and - * offlining timed out in common_cpu_die(). - */ - if (cpu_report_state(cpu) == CPU_DEAD_FROZEN) { - xen_smp_intr_free(cpu); - xen_uninit_lock_cpu(cpu); - } - - /* - * xen_smp_intr_init() needs to run before native_cpu_up() - * so that IPI vectors are set up on the booting CPU before - * it is marked online in native_cpu_up(). - */ - rc = xen_smp_intr_init(cpu); - 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; -} - void __init xen_hvm_smp_init(void) { if (!xen_have_vector_callback) return; smp_ops.smp_prepare_cpus = xen_hvm_smp_prepare_cpus; smp_ops.smp_send_reschedule = xen_smp_send_reschedule; - smp_ops.cpu_up = xen_hvm_cpu_up; smp_ops.cpu_die = xen_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; diff --git a/arch/x86/xen/smp.h b/arch/x86/xen/smp.h index 963d62a35c82..c5c16dc4f694 100644 --- a/arch/x86/xen/smp.h +++ b/arch/x86/xen/smp.h @@ -1,5 +1,6 @@ #ifndef _XEN_SMP_H +#ifdef CONFIG_SMP extern void xen_send_IPI_mask(const struct cpumask *mask, int vector); extern void xen_send_IPI_mask_allbutself(const struct cpumask *mask, @@ -8,6 +9,18 @@ extern void xen_send_IPI_allbutself(int vector); extern void xen_send_IPI_all(int vector); extern void xen_send_IPI_self(int vector); +extern int xen_smp_intr_init(unsigned int cpu); +extern void xen_smp_intr_free(unsigned int cpu); + +#else /* CONFIG_SMP */ + +static inline int xen_smp_intr_init(unsigned int cpu) +{ + return 0; +} +static inline void xen_smp_intr_free(unsigned int cpu) {} +#endif /* CONFIG_SMP */ + #ifdef CONFIG_XEN_PVH extern void xen_pvh_early_cpu_init(int cpu, bool entry); #else -- cgit v1.2.1 From e1c105a9d75a1e9a44eb2f0b10204a6492057e4d Mon Sep 17 00:00:00 2001 From: Boris Ostrovsky Date: Wed, 3 Aug 2016 13:22:28 -0400 Subject: hotplug: Prevent alloc/free of irq descriptors during cpu up/down (again) Now that Xen no longer allocates irqs in _cpu_up() we can restore commit a89941816726 ("hotplug: Prevent alloc/free of irq descriptors during cpu up/down") Signed-off-by: Boris Ostrovsky Acked-by: Thomas Gleixner CC: x86@kernel.org CC: Thomas Gleixner Signed-off-by: David Vrabel --- arch/x86/kernel/smpboot.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'arch/x86') diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 4296beb8fdd3..26b473dc3f82 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -1115,17 +1115,8 @@ int native_cpu_up(unsigned int cpu, struct task_struct *tidle) common_cpu_up(cpu, tidle); - /* - * We have to walk the irq descriptors to setup the vector - * space for the cpu which comes online. Prevent irq - * alloc/free across the bringup. - */ - irq_lock_sparse(); - err = do_boot_cpu(apicid, cpu, tidle); - if (err) { - irq_unlock_sparse(); pr_err("do_boot_cpu failed(%d) to wakeup CPU#%u\n", err, cpu); return -EIO; } @@ -1143,8 +1134,6 @@ int native_cpu_up(unsigned int cpu, struct task_struct *tidle) touch_nmi_watchdog(); } - irq_unlock_sparse(); - return 0; } -- cgit v1.2.1 From 0252937a87e1d46a8261da85cbd99dffe612a2d3 Mon Sep 17 00:00:00 2001 From: Juergen Gross Date: Tue, 2 Aug 2016 09:22:12 +0200 Subject: xen: Make VPMU init message look less scary The default for the Xen hypervisor is to not enable VPMU in order to avoid security issues. In this case the Linux kernel will issue the message "Could not initialize VPMU for cpu 0, error -95" which looks more like an error than a normal state. Change the message to something less scary in case the hypervisor returns EOPNOTSUPP or ENOSYS when trying to activate VPMU. Signed-off-by: Juergen Gross Signed-off-by: David Vrabel --- arch/x86/xen/pmu.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'arch/x86') diff --git a/arch/x86/xen/pmu.c b/arch/x86/xen/pmu.c index 32bdc2c90297..b9fc52556bcc 100644 --- a/arch/x86/xen/pmu.c +++ b/arch/x86/xen/pmu.c @@ -547,8 +547,11 @@ void xen_pmu_init(int cpu) return; fail: - pr_info_once("Could not initialize VPMU for cpu %d, error %d\n", - cpu, err); + if (err == -EOPNOTSUPP || err == -ENOSYS) + pr_info_once("VPMU disabled by hypervisor.\n"); + else + pr_info_once("Could not initialize VPMU for cpu %d, error %d\n", + cpu, err); free_pages((unsigned long)xenpmu_data, 0); } -- cgit v1.2.1 From 4f0fbdf22e739c94ad4c18c790be014dddaedd28 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Thu, 25 Aug 2016 13:23:06 +0200 Subject: xen/grant-table: Use kmalloc_array() in arch_gnttab_valloc() * A multiplication for the size determination of a memory allocation indicated that an array data structure should be processed. Thus reuse the corresponding function "kmalloc_array". This issue was detected by using the Coccinelle software. * Replace the specification of a data type by a pointer dereference to make the corresponding size determination a bit safer according to the Linux coding style convention. Signed-off-by: Markus Elfring Reviewed-by: Juergen Gross Signed-off-by: David Vrabel --- arch/x86/xen/grant-table.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86') diff --git a/arch/x86/xen/grant-table.c b/arch/x86/xen/grant-table.c index de4144c24f1c..809b6c812654 100644 --- a/arch/x86/xen/grant-table.c +++ b/arch/x86/xen/grant-table.c @@ -89,7 +89,7 @@ void arch_gnttab_unmap(void *shared, unsigned long nr_gframes) static int arch_gnttab_valloc(struct gnttab_vm_area *area, unsigned nr_frames) { - area->ptes = kmalloc(sizeof(pte_t *) * nr_frames, GFP_KERNEL); + area->ptes = kmalloc_array(nr_frames, sizeof(*area->ptes), GFP_KERNEL); if (area->ptes == NULL) return -ENOMEM; -- cgit v1.2.1 From 8129554c643b0e1a8336d842cce2f3d595aeeed7 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 12 Sep 2016 11:20:46 +0100 Subject: x86/xen: add missing \n at end of printk warning message The message is missing a \n, add it. Signed-off-by: Colin Ian King Reviewed-by: Juergen Gross Signed-off-by: David Vrabel --- arch/x86/xen/platform-pci-unplug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86') diff --git a/arch/x86/xen/platform-pci-unplug.c b/arch/x86/xen/platform-pci-unplug.c index d37a0c7f82cb..90d1b83cf35f 100644 --- a/arch/x86/xen/platform-pci-unplug.c +++ b/arch/x86/xen/platform-pci-unplug.c @@ -61,7 +61,7 @@ static int check_platform_magic(void) } break; default: - printk(KERN_WARNING "Xen Platform PCI: unknown I/O protocol version"); + printk(KERN_WARNING "Xen Platform PCI: unknown I/O protocol version\n"); return XEN_PLATFORM_ERR_PROTOCOL; } -- cgit v1.2.1 From 4d737042d6c4ee10a632cf94b953169d13955a40 Mon Sep 17 00:00:00 2001 From: Boris Ostrovsky Date: Wed, 7 Sep 2016 13:19:00 -0400 Subject: xen/x86: Convert to hotplug state machine Switch to new CPU hotplug infrastructure. Signed-off-by: Boris Ostrovsky Suggested-by: Sebastian Andrzej Siewior Signed-off-by: David Vrabel --- arch/x86/xen/enlighten.c | 115 ++++++++++++++++++++++++++--------------------- 1 file changed, 65 insertions(+), 50 deletions(-) (limited to 'arch/x86') diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index c7f6b1f90efa..a9ba14ac3aea 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -140,7 +140,9 @@ RESERVE_BRK(shared_info_page_brk, PAGE_SIZE); __read_mostly int xen_have_vector_callback; EXPORT_SYMBOL_GPL(xen_have_vector_callback); -static struct notifier_block xen_cpu_notifier; +static int xen_cpu_up_prepare(unsigned int cpu); +static int xen_cpu_up_online(unsigned int cpu); +static int xen_cpu_dead(unsigned int cpu); /* * Point at some empty memory to start with. We map the real shared_info @@ -1541,6 +1543,24 @@ static void __init xen_dom0_set_legacy_features(void) x86_platform.legacy.rtc = 1; } +static int xen_cpuhp_setup(void) +{ + int rc; + + rc = cpuhp_setup_state_nocalls(CPUHP_XEN_PREPARE, + "XEN_HVM_GUEST_PREPARE", + xen_cpu_up_prepare, xen_cpu_dead); + if (rc >= 0) { + rc = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, + "XEN_HVM_GUEST_ONLINE", + xen_cpu_up_online, NULL); + if (rc < 0) + cpuhp_remove_state_nocalls(CPUHP_XEN_PREPARE); + } + + return rc >= 0 ? 0 : rc; +} + /* First C function to be called on Xen boot */ asmlinkage __visible void __init xen_start_kernel(void) { @@ -1629,7 +1649,7 @@ asmlinkage __visible void __init xen_start_kernel(void) xen_initial_gdt = &per_cpu(gdt_page, 0); xen_smp_init(); - register_cpu_notifier(&xen_cpu_notifier); + WARN_ON(xen_cpuhp_setup()); #ifdef CONFIG_ACPI_NUMA /* @@ -1823,63 +1843,58 @@ static void __init init_hvm_pv_info(void) xen_domain_type = XEN_HVM_DOMAIN; } -static int xen_cpu_notify(struct notifier_block *self, unsigned long action, - void *hcpu) +static int xen_cpu_up_prepare(unsigned int cpu) { - int cpu = (long)hcpu; int rc; - switch (action) { - case CPU_UP_PREPARE: - if (xen_hvm_domain()) { - /* - * This can happen if CPU was offlined earlier and - * offlining timed out in common_cpu_die(). - */ - if (cpu_report_state(cpu) == CPU_DEAD_FROZEN) { - xen_smp_intr_free(cpu); - xen_uninit_lock_cpu(cpu); - } - - if (cpu_acpi_id(cpu) != U32_MAX) - per_cpu(xen_vcpu_id, cpu) = cpu_acpi_id(cpu); - else - per_cpu(xen_vcpu_id, cpu) = cpu; - xen_vcpu_setup(cpu); + if (xen_hvm_domain()) { + /* + * This can happen if CPU was offlined earlier and + * offlining timed out in common_cpu_die(). + */ + if (cpu_report_state(cpu) == CPU_DEAD_FROZEN) { + xen_smp_intr_free(cpu); + xen_uninit_lock_cpu(cpu); } - if (xen_pv_domain() || - (xen_have_vector_callback && - xen_feature(XENFEAT_hvm_safe_pvclock))) - xen_setup_timer(cpu); + if (cpu_acpi_id(cpu) != U32_MAX) + per_cpu(xen_vcpu_id, cpu) = cpu_acpi_id(cpu); + else + per_cpu(xen_vcpu_id, cpu) = cpu; + xen_vcpu_setup(cpu); + } - rc = xen_smp_intr_init(cpu); - if (rc) { - WARN(1, "xen_smp_intr_init() for CPU %d failed: %d\n", - cpu, rc); - return NOTIFY_BAD; - } + if (xen_pv_domain() || + (xen_have_vector_callback && + xen_feature(XENFEAT_hvm_safe_pvclock))) + xen_setup_timer(cpu); - break; - case CPU_ONLINE: - xen_init_lock_cpu(cpu); - break; - case CPU_UP_CANCELED: - xen_smp_intr_free(cpu); - if (xen_pv_domain() || - (xen_have_vector_callback && - xen_feature(XENFEAT_hvm_safe_pvclock))) - xen_teardown_timer(cpu); - break; - default: - break; + rc = xen_smp_intr_init(cpu); + if (rc) { + WARN(1, "xen_smp_intr_init() for CPU %d failed: %d\n", + cpu, rc); + return rc; } - return NOTIFY_OK; + return 0; } -static struct notifier_block xen_cpu_notifier = { - .notifier_call = xen_cpu_notify, -}; +static int xen_cpu_dead(unsigned int cpu) +{ + xen_smp_intr_free(cpu); + + if (xen_pv_domain() || + (xen_have_vector_callback && + xen_feature(XENFEAT_hvm_safe_pvclock))) + xen_teardown_timer(cpu); + + return 0; +} + +static int xen_cpu_up_online(unsigned int cpu) +{ + xen_init_lock_cpu(cpu); + return 0; +} #ifdef CONFIG_KEXEC_CORE static void xen_hvm_shutdown(void) @@ -1910,7 +1925,7 @@ static void __init xen_hvm_guest_init(void) if (xen_feature(XENFEAT_hvm_callback_vector)) xen_have_vector_callback = 1; xen_hvm_smp_init(); - register_cpu_notifier(&xen_cpu_notifier); + WARN_ON(xen_cpuhp_setup()); xen_unplug_emulated_devices(); x86_init.irqs.intr_init = xen_init_IRQ; xen_hvm_init_time_ops(); -- cgit v1.2.1 From 72a9b186292d98494f222226cfd24a1621796209 Mon Sep 17 00:00:00 2001 From: KarimAllah Ahmed Date: Fri, 26 Aug 2016 23:55:36 +0200 Subject: xen: Remove event channel notification through Xen PCI platform device Ever since commit 254d1a3f02eb ("xen/pv-on-hvm kexec: shutdown watches from old kernel") using the INTx interrupt from Xen PCI platform device for event channel notification would just lockup the guest during bootup. postcore_initcall now calls xs_reset_watches which will eventually try to read a value from XenStore and will get stuck on read_reply at XenBus forever since the platform driver is not probed yet and its INTx interrupt handler is not registered yet. That means that the guest can not be notified at this moment of any pending event channels and none of the per-event handlers will ever be invoked (including the XenStore one) and the reply will never be picked up by the kernel. The exact stack where things get stuck during xenbus_init: -xenbus_init -xs_init -xs_reset_watches -xenbus_scanf -xenbus_read -xs_single -xs_single -xs_talkv Vector callbacks have always been the favourite event notification mechanism since their introduction in commit 38e20b07efd5 ("x86/xen: event channels delivery on HVM.") and the vector callback feature has always been advertised for quite some time by Xen that's why INTx was broken for several years now without impacting anyone. Luckily this also means that event channel notification through INTx is basically dead-code which can be safely removed without impacting anybody since it has been effectively disabled for more than 4 years with nobody complaining about it (at least as far as I'm aware of). This commit removes event channel notification through Xen PCI platform device. Cc: Boris Ostrovsky Cc: David Vrabel Cc: Juergen Gross Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Cc: x86@kernel.org Cc: Konrad Rzeszutek Wilk Cc: Bjorn Helgaas Cc: Stefano Stabellini Cc: Julien Grall Cc: Vitaly Kuznetsov Cc: Paul Gortmaker Cc: Ross Lagerwall Cc: xen-devel@lists.xenproject.org Cc: linux-kernel@vger.kernel.org Cc: linux-pci@vger.kernel.org Cc: Anthony Liguori Signed-off-by: KarimAllah Ahmed Reviewed-by: Boris Ostrovsky Signed-off-by: David Vrabel --- arch/x86/include/asm/xen/events.h | 11 ----------- arch/x86/pci/xen.c | 2 +- arch/x86/xen/enlighten.c | 21 ++++++--------------- arch/x86/xen/smp.c | 2 -- arch/x86/xen/time.c | 5 ----- 5 files changed, 7 insertions(+), 34 deletions(-) (limited to 'arch/x86') diff --git a/arch/x86/include/asm/xen/events.h b/arch/x86/include/asm/xen/events.h index e6911caf5bbf..608a79d5a466 100644 --- a/arch/x86/include/asm/xen/events.h +++ b/arch/x86/include/asm/xen/events.h @@ -20,15 +20,4 @@ static inline int xen_irqs_disabled(struct pt_regs *regs) /* No need for a barrier -- XCHG is a barrier on x86. */ #define xchg_xen_ulong(ptr, val) xchg((ptr), (val)) -extern int xen_have_vector_callback; - -/* - * Events delivered via platform PCI interrupts are always - * routed to vcpu 0 and hence cannot be rebound. - */ -static inline bool xen_support_evtchn_rebind(void) -{ - return (!xen_hvm_domain() || xen_have_vector_callback); -} - #endif /* _ASM_X86_XEN_EVENTS_H */ diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index 3a483cb5ac81..bedfab98077a 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c @@ -456,7 +456,7 @@ void __init xen_msi_init(void) int __init pci_xen_hvm_init(void) { - if (!xen_have_vector_callback || !xen_feature(XENFEAT_hvm_pirqs)) + if (!xen_feature(XENFEAT_hvm_pirqs)) return 0; #ifdef CONFIG_ACPI diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index a9ba14ac3aea..366b6aed4a8e 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -137,8 +137,6 @@ struct shared_info xen_dummy_shared_info; void *xen_initial_gdt; RESERVE_BRK(shared_info_page_brk, PAGE_SIZE); -__read_mostly int xen_have_vector_callback; -EXPORT_SYMBOL_GPL(xen_have_vector_callback); static int xen_cpu_up_prepare(unsigned int cpu); static int xen_cpu_up_online(unsigned int cpu); @@ -1524,10 +1522,7 @@ static void __init xen_pvh_early_guest_init(void) if (!xen_feature(XENFEAT_auto_translated_physmap)) return; - if (!xen_feature(XENFEAT_hvm_callback_vector)) - return; - - xen_have_vector_callback = 1; + BUG_ON(!xen_feature(XENFEAT_hvm_callback_vector)); xen_pvh_early_cpu_init(0, false); xen_pvh_set_cr_flags(0); @@ -1864,9 +1859,7 @@ static int xen_cpu_up_prepare(unsigned int cpu) xen_vcpu_setup(cpu); } - if (xen_pv_domain() || - (xen_have_vector_callback && - xen_feature(XENFEAT_hvm_safe_pvclock))) + if (xen_pv_domain() || xen_feature(XENFEAT_hvm_safe_pvclock)) xen_setup_timer(cpu); rc = xen_smp_intr_init(cpu); @@ -1882,9 +1875,7 @@ static int xen_cpu_dead(unsigned int cpu) { xen_smp_intr_free(cpu); - if (xen_pv_domain() || - (xen_have_vector_callback && - xen_feature(XENFEAT_hvm_safe_pvclock))) + if (xen_pv_domain() || xen_feature(XENFEAT_hvm_safe_pvclock)) xen_teardown_timer(cpu); return 0; @@ -1922,8 +1913,8 @@ static void __init xen_hvm_guest_init(void) xen_panic_handler_init(); - if (xen_feature(XENFEAT_hvm_callback_vector)) - xen_have_vector_callback = 1; + BUG_ON(!xen_feature(XENFEAT_hvm_callback_vector)); + xen_hvm_smp_init(); WARN_ON(xen_cpuhp_setup()); xen_unplug_emulated_devices(); @@ -1961,7 +1952,7 @@ bool xen_hvm_need_lapic(void) return false; if (!xen_hvm_domain()) return false; - if (xen_feature(XENFEAT_hvm_pirqs) && xen_have_vector_callback) + if (xen_feature(XENFEAT_hvm_pirqs)) return false; return true; } diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 137afbbd0590..311acad7dad2 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -765,8 +765,6 @@ static void __init xen_hvm_smp_prepare_cpus(unsigned int max_cpus) void __init xen_hvm_smp_init(void) { - if (!xen_have_vector_callback) - return; smp_ops.smp_prepare_cpus = xen_hvm_smp_prepare_cpus; smp_ops.smp_send_reschedule = xen_smp_send_reschedule; smp_ops.cpu_die = xen_cpu_die; diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c index 67356d29d74d..33d8f6a7829d 100644 --- a/arch/x86/xen/time.c +++ b/arch/x86/xen/time.c @@ -432,11 +432,6 @@ static void xen_hvm_setup_cpu_clockevents(void) void __init xen_hvm_init_time_ops(void) { - /* vector callback is needed otherwise we cannot receive interrupts - * on cpu > 0 and at this point we don't know how many cpus are - * available */ - if (!xen_have_vector_callback) - return; if (!xen_feature(XENFEAT_hvm_safe_pvclock)) { printk(KERN_INFO "Xen doesn't support pvclock on HVM," "disable pv timer\n"); -- cgit v1.2.1 From 565fdc6a2afeb14e654a8d9ebc792afb9d2c0019 Mon Sep 17 00:00:00 2001 From: Boris Ostrovsky Date: Sun, 2 Oct 2016 18:45:19 -0400 Subject: xen/x86: Initialize per_cpu(xen_vcpu, 0) a little earlier xen_cpuhp_setup() calls mutex_lock() which, when CONFIG_DEBUG_MUTEXES is defined, ends up calling xen_save_fl(). That routine expects per_cpu(xen_vcpu, 0) to be already initialized. Signed-off-by: Boris Ostrovsky Reported-by: Sander Eikelenboom Signed-off-by: David Vrabel --- arch/x86/xen/enlighten.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch/x86') diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 366b6aed4a8e..96c2dea798a1 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1644,7 +1644,6 @@ asmlinkage __visible void __init xen_start_kernel(void) xen_initial_gdt = &per_cpu(gdt_page, 0); xen_smp_init(); - WARN_ON(xen_cpuhp_setup()); #ifdef CONFIG_ACPI_NUMA /* @@ -1658,6 +1657,8 @@ asmlinkage __visible void __init xen_start_kernel(void) possible map and a non-dummy shared_info. */ per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0]; + WARN_ON(xen_cpuhp_setup()); + local_irq_disable(); early_boot_irqs_disabled = true; -- cgit v1.2.1 From a6a198bc60e6c980a56eca24d33dc7f29139f8ea Mon Sep 17 00:00:00 2001 From: Boris Ostrovsky Date: Wed, 5 Oct 2016 13:09:33 -0400 Subject: xen/x86: Update topology map for PV VCPUs Early during boot topology_update_package_map() computes logical_pkg_ids for all present processors. Later, when processors are brought up, identify_cpu() updates these values based on phys_pkg_id which is a function of initial_apicid. On PV guests the latter may point to a non-existing node, causing logical_pkg_ids to be set to -1. Intel's RAPL uses logical_pkg_id (as topology_logical_package_id()) to index its arrays and therefore in this case will point to index 65535 (since logical_pkg_id is a u16). This could lead to either a crash or may actually access random memory location. As a workaround, we recompute topology during CPU bringup to reset logical_pkg_id to a valid value. (The reason for initial_apicid being bogus is because it is initial_apicid of the processor from which the guest is launched. This value is CPUID(1).EBX[31:24]) Signed-off-by: Boris Ostrovsky Cc: stable@vger.kernel.org Signed-off-by: David Vrabel --- arch/x86/xen/smp.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'arch/x86') diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 311acad7dad2..9fa27ceeecfd 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -87,6 +87,12 @@ static void cpu_bringup(void) cpu_data(cpu).x86_max_cores = 1; set_cpu_sibling_map(cpu); + /* + * identify_cpu() may have set logical_pkg_id to -1 due + * to incorrect phys_proc_id. Let's re-comupte it. + */ + topology_update_package_map(apic->cpu_present_to_apicid(cpu), cpu); + xen_setup_cpu_clockevents(); notify_cpu_starting(cpu); -- cgit v1.2.1