core/smp changes for v4.9
Subsystems (6)
Linus,
Please pull the latest core-smp-for-linus git tree from:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git core-smp-for-linus
# HEAD: 8db549491c4a3ce9e1d509b75f78516e497f48ec smp: Allocate smp_call_on_cpu() workqueue on stack too
Two main change is generic vCPU pinning and physical CPU SMP-call support, for Xen to be able to perform certain calls on specific physical CPUs - by Juergen Gross.
Thanks,
Ingo
------------------>
Juergen Gross (6):
xen: Sync xen header
virt, sched: Add generic vCPU pinning support
smp: Add function to execute a function synchronously on a CPU
xen: Add xen_pin_vcpu() to support calling functions on a dedicated pCPU
dcdbas: Make use of smp_call_on_cpu()
hwmon: Use smp_call_on_cpu() for dell-smm i8k
Peter Zijlstra (1):
smp: Allocate smp_call_on_cpu() workqueue on stack too
MAINTAINERS | 1 + arch/x86/include/asm/hypervisor.h | 4 ++ arch/x86/kernel/cpu/hypervisor.c | 11 +++++ arch/x86/xen/enlighten.c | 40 +++++++++++++++ drivers/firmware/dcdbas.c | 51 +++++++++---------- drivers/hwmon/dell-smm-hwmon.c | 36 ++++++++------ include/linux/hypervisor.h | 17 +++++++ include/linux/smp.h | 3 ++ include/xen/interface/sched.h | 100 +++++++++++++++++++++++++++++++------- kernel/smp.c | 52 ++++++++++++++++++++ kernel/up.c | 18 +++++++ 11 files changed, 274 insertions(+), 59 deletions(-) create mode 100644 include/linux/hypervisor.h
MAINTAINERS +1 -0
@@ -8845,6 +8845,7 @@ S: Supported F: Documentation/virtual/paravirt_ops.txt F: arch/*/kernel/paravirt* F: arch/*/include/asm/paravirt.h +F: include/linux/hypervisor.h PARIDE DRIVERS FOR PARALLEL PORT IDE DEVICES M: Tim Waugh <[email protected]>
arch/x86/include/asm/hypervisor.h +4 -0
@@ -43,6 +43,9 @@ struct hypervisor_x86 {/* X2APIC detection (run once per boot) */ bool (*x2apic_available)(void ); + +/* pin current vcpu to specified physical cpu (run rarely) */ +void (*pin_vcpu)(int ); };extern const struct hypervisor_x86 *x86_hyper;
@@ -56,6 +59,7 @@ extern const struct hypervisor_x86 x86_hyper_kvm;extern void init_hypervisor (struct cpuinfo_x86 *c);extern void init_hypervisor_platform (void );extern bool hypervisor_x2apic_available (void ); +extern void hypervisor_pin_vcpu (int cpu);#else static inline void init_hypervisor (struct cpuinfo_x86 *c) { }static inline void init_hypervisor_platform (void ) { }
arch/x86/kernel/cpu/hypervisor.c +11 -0
@@ -86,3 +86,14 @@ bool __init hypervisor_x2apic_available(void) x86_hyper->x2apic_available && x86_hyper->x2apic_available (); } + +void hypervisor_pin_vcpu (int cpu) +{ +if (!x86_hyper) +return ; + +if (x86_hyper->pin_vcpu) + x86_hyper->pin_vcpu (cpu); +else +WARN_ONCE (1 ,"vcpu pinning requested but not supported!\n" ); +}
arch/x86/xen/enlighten.c +40 -0
@@ -1925,6 +1925,45 @@ static void xen_set_cpu_features(struct cpuinfo_x86 *c) } } +static void xen_pin_vcpu (int cpu) +{ +static bool disable_pinning; +struct sched_pin_override pin_override; +int ret; + +if (disable_pinning) +return ; + + pin_override.pcpu = cpu; + ret =HYPERVISOR_sched_op (SCHEDOP_pin_override, &pin_override); + +/* Ignore errors when removing override. */ +if (cpu <0 ) +return ; + +switch (ret) { +case -ENOSYS : +pr_warn ("Unable to pin on physical cpu %d. In case of problems consider vcpu pinning.\n" , + cpu); + disable_pinning = true; +break ; +case -EPERM : +WARN (1 ,"Trying to pin vcpu without having privilege to do so\n" ); + disable_pinning = true; +break ; +case -EINVAL : +case -EBUSY : +pr_warn ("Physical cpu %d not available for pinning. Check Xen cpu configuration.\n" , + cpu); +break ; +case 0 : +break ; +default : +WARN (1 ,"rc %d while trying to pin vcpu\n" , ret); + disable_pinning = true; + } +} +const struct hypervisor_x86 x86_hyper_xen = { .name ="Xen" , .detect = xen_platform,
@@ -1933,6 +1972,7 @@ const struct hypervisor_x86 x86_hyper_xen = {#endif .x2apic_available = xen_x2apic_para_available, .set_cpu_features = xen_set_cpu_features, + .pin_vcpu = xen_pin_vcpu, };EXPORT_SYMBOL (x86_hyper_xen);
drivers/firmware/dcdbas.c +26 -25
74 lines not on this page · raw message
drivers/hwmon/dell-smm-hwmon.c +20 -16
@@ -21,6 +21,7 @@#define pr_fmt (fmt) KBUILD_MODNAME ": " fmt +#include <linux/cpu.h> #include <linux/delay.h> #include <linux/module.h> #include <linux/types.h>
@@ -36,6 +37,7 @@#include <linux/io.h> #include <linux/sched.h> #include <linux/ctype.h> +#include <linux/smp.h> #include <linux/i8k.h>
@@ -134,11 +136,11 @@ static inline const char *i8k_get_dmi_data(int field)/* * Call the System Management Mode BIOS. Code provided by Jonathan Buzzard. */ -static int i8k_smm (struct smm_regs *regs) +static int i8k_smm_func (void *par) {int rc; +struct smm_regs *regs = par;int eax = regs->eax; -cpumask_var_t old_mask;#ifdef DEBUG int ebx = regs->ebx;
@@ -149,16 +151,8 @@ static int i8k_smm(struct smm_regs *regs)#endif /* SMM requires CPU 0 */ -if (!alloc_cpumask_var (&old_mask,GFP_KERNEL )) -return -ENOMEM ; -cpumask_copy (old_mask, ¤t->cpus_allowed); - rc =set_cpus_allowed_ptr (current,cpumask_of (0 )); -if (rc) - goto out; -if (smp_processor_id () !=0 ) { - rc = -EBUSY ; - goto out; - } +if (smp_processor_id () !=0 ) +return -EBUSY ;#if defined(CONFIG_X86_64 ) asm volatile("pushq %%rax\n\t"
@@ -216,10 +210,6 @@ static int i8k_smm(struct smm_regs *regs)if (rc !=0 || (regs->eax &0xffff ) ==0xffff || regs->eax == eax) rc = -EINVAL ; -out: -set_cpus_allowed_ptr (current, old_mask); -free_cpumask_var (old_mask); -#ifdef DEBUG rettime =ktime_get (); delta =ktime_sub (rettime, calltime);
@@ -232,6 +222,20 @@ static int i8k_smm(struct smm_regs *regs) }/* +* Call the System Management Mode BIOS. +*/ +static int i8k_smm (struct smm_regs *regs) +{ +int ret; + +get_online_cpus (); + ret =smp_call_on_cpu (0 , i8k_smm_func, regs, true); +put_online_cpus (); + +return ret; +} + +/* * Read the fan status. */ static int i8k_get_fan_status (int fan)
include/linux/hypervisor.h new file +17 -0
@@ -0,0 +1,17 @@ +#ifndef __LINUX_HYPEVISOR_H +#define __LINUX_HYPEVISOR_H + +/* +* Generic Hypervisor support +* Juergen Gross <[email protected]> +*/ + +#ifdef CONFIG_HYPERVISOR_GUEST +#include <asm/hypervisor.h> +#else +static inline void hypervisor_pin_vcpu (int cpu) +{ +} +#endif + +#endif /* __LINUX_HYPEVISOR_H */
include/linux/smp.h +3 -0
@@ -196,6 +196,9 @@ extern void arch_enable_nonboot_cpus_end(void);void smp_setup_processor_id (void ); +int smp_call_on_cpu (unsigned int cpu,int (*func)(void *),void *par, +bool phys); +/* SMP core functions */ int smpcfd_prepare_cpu (unsigned int cpu);int smpcfd_dead_cpu (unsigned int cpu);
include/xen/interface/sched.h +82 -18
166 lines not on this page · raw message
kernel/smp.c +52 -0
61 lines not on this page · raw message
kernel/up.c +18 -0
@@ -6,6 +6,7 @@#include <linux/kernel.h> #include <linux/export.h> #include <linux/smp.h> +#include <linux/hypervisor.h> int smp_call_function_single (int cpu,void (*func) (void *info),void *info,int wait)
@@ -82,3 +83,20 @@ void on_each_cpu_cond(bool (*cond_func)(int cpu, void *info),preempt_enable (); }EXPORT_SYMBOL (on_each_cpu_cond); + +int smp_call_on_cpu (unsigned int cpu,int (*func)(void *),void *par,bool phys) +{ +int ret; + +if (cpu !=0 ) +return -ENXIO ; + +if (phys) +hypervisor_pin_vcpu (0 ); + ret =func (par); +if (phys) +hypervisor_pin_vcpu (-1 ); + +return ret; +} +EXPORT_SYMBOL_GPL (smp_call_on_cpu);