aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-10-03 14:02:39 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-10-03 14:02:39 -0400
commitd7a0dab82fef61bebd34f2bbb9314b075153b646 (patch)
tree1ec0a1d31ed8231bcce7f20c6b289e57a8969ca9
parent4b978934a440c1aafce986353001b03289eaa040 (diff)
parent8db549491c4a3ce9e1d509b75f78516e497f48ec (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--MAINTAINERS1
-rw-r--r--arch/x86/include/asm/hypervisor.h4
-rw-r--r--arch/x86/kernel/cpu/hypervisor.c11
-rw-r--r--arch/x86/xen/enlighten.c40
-rw-r--r--drivers/firmware/dcdbas.c51
-rw-r--r--drivers/hwmon/dell-smm-hwmon.c36
-rw-r--r--include/linux/hypervisor.h17
-rw-r--r--include/linux/smp.h3
-rw-r--r--include/xen/interface/sched.h100
-rw-r--r--kernel/smp.c52
-rw-r--r--kernel/up.c18
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
8860F: Documentation/virtual/paravirt_ops.txt 8860F: Documentation/virtual/paravirt_ops.txt
8861F: arch/*/kernel/paravirt* 8861F: arch/*/kernel/paravirt*
8862F: arch/*/include/asm/paravirt.h 8862F: arch/*/include/asm/paravirt.h
8863F: include/linux/hypervisor.h
8863 8864
8864PARIDE DRIVERS FOR PARALLEL PORT IDE DEVICES 8865PARIDE DRIVERS FOR PARALLEL PORT IDE DEVICES
8865M: Tim Waugh <tim@cyberelk.net> 8866M: 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
48extern const struct hypervisor_x86 *x86_hyper; 51extern const struct hypervisor_x86 *x86_hyper;
@@ -56,6 +59,7 @@ extern const struct hypervisor_x86 x86_hyper_kvm;
56extern void init_hypervisor(struct cpuinfo_x86 *c); 59extern void init_hypervisor(struct cpuinfo_x86 *c);
57extern void init_hypervisor_platform(void); 60extern void init_hypervisor_platform(void);
58extern bool hypervisor_x2apic_available(void); 61extern bool hypervisor_x2apic_available(void);
62extern void hypervisor_pin_vcpu(int cpu);
59#else 63#else
60static inline void init_hypervisor(struct cpuinfo_x86 *c) { } 64static inline void init_hypervisor(struct cpuinfo_x86 *c) { }
61static inline void init_hypervisor_platform(void) { } 65static 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
90void 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
1928static 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
1928const struct hypervisor_x86 x86_hyper_xen = { 1967const 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};
1937EXPORT_SYMBOL(x86_hyper_xen); 1977EXPORT_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/** 242static int raise_smi(void *par)
242 * dcdbas_smi_request: generate SMI request
243 *
244 * Called with smi_data_lock.
245 */
246int 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, &current->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
283out: 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 */
272int 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();