diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-03 14:02:39 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-03 14:02:39 -0400 |
| commit | d7a0dab82fef61bebd34f2bbb9314b075153b646 (patch) | |
| tree | 1ec0a1d31ed8231bcce7f20c6b289e57a8969ca9 | |
| parent | 4b978934a440c1aafce986353001b03289eaa040 (diff) | |
| parent | 8db549491c4a3ce9e1d509b75f78516e497f48ec (diff) | |
Merge branch 'core-smp-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull core SMP updates from Ingo Molnar:
"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"
* 'core-smp-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
smp: Allocate smp_call_on_cpu() workqueue on stack too
hwmon: Use smp_call_on_cpu() for dell-smm i8k
dcdbas: Make use of smp_call_on_cpu()
xen: Add xen_pin_vcpu() to support calling functions on a dedicated pCPU
smp: Add function to execute a function synchronously on a CPU
virt, sched: Add generic vCPU pinning support
xen: Sync xen header
| -rw-r--r-- | MAINTAINERS | 1 | ||||
| -rw-r--r-- | arch/x86/include/asm/hypervisor.h | 4 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/hypervisor.c | 11 | ||||
| -rw-r--r-- | arch/x86/xen/enlighten.c | 40 | ||||
| -rw-r--r-- | drivers/firmware/dcdbas.c | 51 | ||||
| -rw-r--r-- | drivers/hwmon/dell-smm-hwmon.c | 36 | ||||
| -rw-r--r-- | include/linux/hypervisor.h | 17 | ||||
| -rw-r--r-- | include/linux/smp.h | 3 | ||||
| -rw-r--r-- | include/xen/interface/sched.h | 100 | ||||
| -rw-r--r-- | kernel/smp.c | 52 | ||||
| -rw-r--r-- | kernel/up.c | 18 |
11 files changed, 274 insertions, 59 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index c8926c1acd22..f2ae3a4bc5c2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -8860,6 +8860,7 @@ S: Supported | |||
| 8860 | F: Documentation/virtual/paravirt_ops.txt | 8860 | F: Documentation/virtual/paravirt_ops.txt |
| 8861 | F: arch/*/kernel/paravirt* | 8861 | F: arch/*/kernel/paravirt* |
| 8862 | F: arch/*/include/asm/paravirt.h | 8862 | F: arch/*/include/asm/paravirt.h |
| 8863 | F: include/linux/hypervisor.h | ||
| 8863 | 8864 | ||
| 8864 | PARIDE DRIVERS FOR PARALLEL PORT IDE DEVICES | 8865 | PARIDE DRIVERS FOR PARALLEL PORT IDE DEVICES |
| 8865 | M: Tim Waugh <tim@cyberelk.net> | 8866 | M: Tim Waugh <tim@cyberelk.net> |
diff --git a/arch/x86/include/asm/hypervisor.h b/arch/x86/include/asm/hypervisor.h index 055ea9941dd5..67942b6ad4b7 100644 --- a/arch/x86/include/asm/hypervisor.h +++ b/arch/x86/include/asm/hypervisor.h | |||
| @@ -43,6 +43,9 @@ struct hypervisor_x86 { | |||
| 43 | 43 | ||
| 44 | /* X2APIC detection (run once per boot) */ | 44 | /* X2APIC detection (run once per boot) */ |
| 45 | bool (*x2apic_available)(void); | 45 | bool (*x2apic_available)(void); |
| 46 | |||
| 47 | /* pin current vcpu to specified physical cpu (run rarely) */ | ||
| 48 | void (*pin_vcpu)(int); | ||
| 46 | }; | 49 | }; |
| 47 | 50 | ||
| 48 | extern const struct hypervisor_x86 *x86_hyper; | 51 | extern const struct hypervisor_x86 *x86_hyper; |
| @@ -56,6 +59,7 @@ extern const struct hypervisor_x86 x86_hyper_kvm; | |||
| 56 | extern void init_hypervisor(struct cpuinfo_x86 *c); | 59 | extern void init_hypervisor(struct cpuinfo_x86 *c); |
| 57 | extern void init_hypervisor_platform(void); | 60 | extern void init_hypervisor_platform(void); |
| 58 | extern bool hypervisor_x2apic_available(void); | 61 | extern bool hypervisor_x2apic_available(void); |
| 62 | extern void hypervisor_pin_vcpu(int cpu); | ||
| 59 | #else | 63 | #else |
| 60 | static inline void init_hypervisor(struct cpuinfo_x86 *c) { } | 64 | static inline void init_hypervisor(struct cpuinfo_x86 *c) { } |
| 61 | static inline void init_hypervisor_platform(void) { } | 65 | static inline void init_hypervisor_platform(void) { } |
diff --git a/arch/x86/kernel/cpu/hypervisor.c b/arch/x86/kernel/cpu/hypervisor.c index 27e46658ebe3..35691a6b0d32 100644 --- a/arch/x86/kernel/cpu/hypervisor.c +++ b/arch/x86/kernel/cpu/hypervisor.c | |||
| @@ -86,3 +86,14 @@ bool __init hypervisor_x2apic_available(void) | |||
| 86 | x86_hyper->x2apic_available && | 86 | x86_hyper->x2apic_available && |
| 87 | x86_hyper->x2apic_available(); | 87 | x86_hyper->x2apic_available(); |
| 88 | } | 88 | } |
| 89 | |||
| 90 | void hypervisor_pin_vcpu(int cpu) | ||
| 91 | { | ||
| 92 | if (!x86_hyper) | ||
| 93 | return; | ||
| 94 | |||
| 95 | if (x86_hyper->pin_vcpu) | ||
| 96 | x86_hyper->pin_vcpu(cpu); | ||
| 97 | else | ||
| 98 | WARN_ONCE(1, "vcpu pinning requested but not supported!\n"); | ||
| 99 | } | ||
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index b86ebb1a9a7f..bc9aaba01a22 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
| @@ -1925,6 +1925,45 @@ static void xen_set_cpu_features(struct cpuinfo_x86 *c) | |||
| 1925 | } | 1925 | } |
| 1926 | } | 1926 | } |
| 1927 | 1927 | ||
| 1928 | static void xen_pin_vcpu(int cpu) | ||
| 1929 | { | ||
| 1930 | static bool disable_pinning; | ||
| 1931 | struct sched_pin_override pin_override; | ||
| 1932 | int ret; | ||
| 1933 | |||
| 1934 | if (disable_pinning) | ||
| 1935 | return; | ||
| 1936 | |||
| 1937 | pin_override.pcpu = cpu; | ||
| 1938 | ret = HYPERVISOR_sched_op(SCHEDOP_pin_override, &pin_override); | ||
| 1939 | |||
| 1940 | /* Ignore errors when removing override. */ | ||
| 1941 | if (cpu < 0) | ||
| 1942 | return; | ||
| 1943 | |||
| 1944 | switch (ret) { | ||
| 1945 | case -ENOSYS: | ||
| 1946 | pr_warn("Unable to pin on physical cpu %d. In case of problems consider vcpu pinning.\n", | ||
| 1947 | cpu); | ||
| 1948 | disable_pinning = true; | ||
| 1949 | break; | ||
| 1950 | case -EPERM: | ||
| 1951 | WARN(1, "Trying to pin vcpu without having privilege to do so\n"); | ||
| 1952 | disable_pinning = true; | ||
| 1953 | break; | ||
| 1954 | case -EINVAL: | ||
| 1955 | case -EBUSY: | ||
| 1956 | pr_warn("Physical cpu %d not available for pinning. Check Xen cpu configuration.\n", | ||
| 1957 | cpu); | ||
| 1958 | break; | ||
| 1959 | case 0: | ||
| 1960 | break; | ||
| 1961 | default: | ||
| 1962 | WARN(1, "rc %d while trying to pin vcpu\n", ret); | ||
| 1963 | disable_pinning = true; | ||
| 1964 | } | ||
| 1965 | } | ||
| 1966 | |||
| 1928 | const struct hypervisor_x86 x86_hyper_xen = { | 1967 | const struct hypervisor_x86 x86_hyper_xen = { |
| 1929 | .name = "Xen", | 1968 | .name = "Xen", |
| 1930 | .detect = xen_platform, | 1969 | .detect = xen_platform, |
| @@ -1933,6 +1972,7 @@ const struct hypervisor_x86 x86_hyper_xen = { | |||
| 1933 | #endif | 1972 | #endif |
| 1934 | .x2apic_available = xen_x2apic_para_available, | 1973 | .x2apic_available = xen_x2apic_para_available, |
| 1935 | .set_cpu_features = xen_set_cpu_features, | 1974 | .set_cpu_features = xen_set_cpu_features, |
| 1975 | .pin_vcpu = xen_pin_vcpu, | ||
| 1936 | }; | 1976 | }; |
| 1937 | EXPORT_SYMBOL(x86_hyper_xen); | 1977 | EXPORT_SYMBOL(x86_hyper_xen); |
| 1938 | 1978 | ||
diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c index 829eec8959f2..2fe1a130189f 100644 --- a/drivers/firmware/dcdbas.c +++ b/drivers/firmware/dcdbas.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
| 24 | #include <linux/dma-mapping.h> | 24 | #include <linux/dma-mapping.h> |
| 25 | #include <linux/errno.h> | 25 | #include <linux/errno.h> |
| 26 | #include <linux/cpu.h> | ||
| 26 | #include <linux/gfp.h> | 27 | #include <linux/gfp.h> |
| 27 | #include <linux/init.h> | 28 | #include <linux/init.h> |
| 28 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
| @@ -238,33 +239,14 @@ static ssize_t host_control_on_shutdown_store(struct device *dev, | |||
| 238 | return count; | 239 | return count; |
| 239 | } | 240 | } |
| 240 | 241 | ||
| 241 | /** | 242 | static int raise_smi(void *par) |
| 242 | * dcdbas_smi_request: generate SMI request | ||
| 243 | * | ||
| 244 | * Called with smi_data_lock. | ||
| 245 | */ | ||
| 246 | int dcdbas_smi_request(struct smi_cmd *smi_cmd) | ||
| 247 | { | 243 | { |
| 248 | cpumask_var_t old_mask; | 244 | struct smi_cmd *smi_cmd = par; |
| 249 | int ret = 0; | ||
| 250 | |||
| 251 | if (smi_cmd->magic != SMI_CMD_MAGIC) { | ||
| 252 | dev_info(&dcdbas_pdev->dev, "%s: invalid magic value\n", | ||
| 253 | __func__); | ||
| 254 | return -EBADR; | ||
| 255 | } | ||
| 256 | 245 | ||
| 257 | /* SMI requires CPU 0 */ | ||
| 258 | if (!alloc_cpumask_var(&old_mask, GFP_KERNEL)) | ||
| 259 | return -ENOMEM; | ||
| 260 | |||
| 261 | cpumask_copy(old_mask, ¤t->cpus_allowed); | ||
| 262 | set_cpus_allowed_ptr(current, cpumask_of(0)); | ||
| 263 | if (smp_processor_id() != 0) { | 246 | if (smp_processor_id() != 0) { |
| 264 | dev_dbg(&dcdbas_pdev->dev, "%s: failed to get CPU 0\n", | 247 | dev_dbg(&dcdbas_pdev->dev, "%s: failed to get CPU 0\n", |
| 265 | __func__); | 248 | __func__); |
| 266 | ret = -EBUSY; | 249 | return -EBUSY; |
| 267 | goto out; | ||
| 268 | } | 250 | } |
| 269 | 251 | ||
| 270 | /* generate SMI */ | 252 | /* generate SMI */ |
| @@ -280,9 +262,28 @@ int dcdbas_smi_request(struct smi_cmd *smi_cmd) | |||
| 280 | : "memory" | 262 | : "memory" |
| 281 | ); | 263 | ); |
| 282 | 264 | ||
| 283 | out: | 265 | return 0; |
| 284 | set_cpus_allowed_ptr(current, old_mask); | 266 | } |
| 285 | free_cpumask_var(old_mask); | 267 | /** |
| 268 | * dcdbas_smi_request: generate SMI request | ||
| 269 | * | ||
| 270 | * Called with smi_data_lock. | ||
| 271 | */ | ||
| 272 | int dcdbas_smi_request(struct smi_cmd *smi_cmd) | ||
| 273 | { | ||
| 274 | int ret; | ||
| 275 | |||
| 276 | if (smi_cmd->magic != SMI_CMD_MAGIC) { | ||
| 277 | dev_info(&dcdbas_pdev->dev, "%s: invalid magic value\n", | ||
| 278 | __func__); | ||
| 279 | return -EBADR; | ||
| 280 | } | ||
| 281 | |||
| 282 | /* SMI requires CPU 0 */ | ||
| 283 | get_online_cpus(); | ||
