[PATCH 1/4] staging: unisys: detect s-Par firmware

Ken Cox jkc at redhat.com
Thu Apr 24 18:57:09 UTC 2014


From: Benjamin Romer <benjamin.romer at unisys.com>

This patch adds support for detection of s-Par firmware by checking for the hypervisor bit in the CPU capabilities, and then querying the hypervisor ID cpuid leaf.

This functionality will be used by the unisys drivers to determine if
they are being loaded on an s-Par platform and refuse to load if no
s-Par firmware is present.

This fixes a problem reported from upstream where a panic occurs if the
unisys drivers are loaded on a non s-Par system.

Reported-by: Fengguang Wu <fengguang.wu at intel.com>
Signed-off-by: Benjamin Romer <benjamin.romer at unisys.com>
Tested-by: Benjamin Romer <benjamin.romer at unisys.com>
Signed-off-by: Ken Cox <jkc at redhat.com>
Tested-by: Ken Cox <jkc at redhat.com>
---
 arch/x86/include/asm/hypervisor.h |  1 +
 arch/x86/kernel/cpu/Makefile      |  2 +-
 arch/x86/kernel/cpu/hypervisor.c  |  3 +++
 arch/x86/kernel/cpu/unisys_spar.c | 51 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 56 insertions(+), 1 deletion(-)
 create mode 100644 arch/x86/kernel/cpu/unisys_spar.c

diff --git a/arch/x86/include/asm/hypervisor.h b/arch/x86/include/asm/hypervisor.h
index e42f758..3a86e0e 100644
--- a/arch/x86/include/asm/hypervisor.h
+++ b/arch/x86/include/asm/hypervisor.h
@@ -52,6 +52,7 @@ extern const struct hypervisor_x86 x86_hyper_vmware;
 extern const struct hypervisor_x86 x86_hyper_ms_hyperv;
 extern const struct hypervisor_x86 x86_hyper_xen_hvm;
 extern const struct hypervisor_x86 x86_hyper_kvm;
+extern const struct hypervisor_x86 x86_hyper_unisys_spar;
 
 extern void init_hypervisor(struct cpuinfo_x86 *c);
 extern void init_hypervisor_platform(void);
diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile
index 7fd54f0..a64ee5a 100644
--- a/arch/x86/kernel/cpu/Makefile
+++ b/arch/x86/kernel/cpu/Makefile
@@ -46,7 +46,7 @@ obj-$(CONFIG_MICROCODE)			+= microcode/
 
 obj-$(CONFIG_X86_LOCAL_APIC)		+= perfctr-watchdog.o perf_event_amd_ibs.o
 
-obj-$(CONFIG_HYPERVISOR_GUEST)		+= vmware.o hypervisor.o mshyperv.o
+obj-$(CONFIG_HYPERVISOR_GUEST)		+= vmware.o hypervisor.o mshyperv.o unisys_spar.o
 
 quiet_cmd_mkcapflags = MKCAP   $@
       cmd_mkcapflags = $(CONFIG_SHELL) $(srctree)/$(src)/mkcapflags.sh $< $@
diff --git a/arch/x86/kernel/cpu/hypervisor.c b/arch/x86/kernel/cpu/hypervisor.c
index 36ce402..ba92d14 100644
--- a/arch/x86/kernel/cpu/hypervisor.c
+++ b/arch/x86/kernel/cpu/hypervisor.c
@@ -35,6 +35,9 @@ static const __initconst struct hypervisor_x86 * const hypervisors[] =
 #ifdef CONFIG_KVM_GUEST
 	&x86_hyper_kvm,
 #endif
+#ifdef CONFIG_UNISYSSPAR
+	&x86_hyper_unisys_spar,
+#endif
 };
 
 const struct hypervisor_x86 *x86_hyper;
diff --git a/arch/x86/kernel/cpu/unisys_spar.c b/arch/x86/kernel/cpu/unisys_spar.c
new file mode 100644
index 0000000..264f309
--- /dev/null
+++ b/arch/x86/kernel/cpu/unisys_spar.c
@@ -0,0 +1,51 @@
+/* unisys_spar.c
+ *
+ * Copyright (C) 2014 - 2014 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#include <asm/hypervisor.h>
+
+/* s-Par uses the Intel processor's VT-X features to separate groups of
+ * processors into partitions. The firmware sets the hypervisor bit and
+ * reports an ID in the HV capabilities leaf so that the partition's OS
+ * knows s-Par is present and managing the processors.
+ */
+
+#define UNISYS_SPAR_LEAF_ID 0x40000000
+
+/* The s-Par leaf ID returns "UnisysSpar64" encoded across ebx, ecx, edx */
+#define UNISYS_SPAR_ID_EBX 0x73696e55
+#define UNISYS_SPAR_ID_ECX 0x70537379
+#define UNISYS_SPAR_ID_EDX 0x34367261
+
+static uint32_t unisys_spar_detect(void)
+{
+	if (cpu_has_hypervisor) {
+		unsigned int eax, ebx, ecx, edx;
+
+		/* check the ID */
+		cpuid(UNISYS_SPAR_LEAF_ID, &eax, &ebx, &ecx, &edx);
+		return  (ebx == UNISYS_SPAR_ID_EBX) &&
+			(ecx == UNISYS_SPAR_ID_ECX) &&
+			(edx == UNISYS_SPAR_ID_EDX);
+	} else
+		return 0;
+}
+
+const __refconst struct hypervisor_x86 x86_hyper_unisys_spar = {
+	.name			= "Unisys s-Par(R)",
+	.detect			= unisys_spar_detect,
+};
+EXPORT_SYMBOL(x86_hyper_unisys_spar);
-- 
1.8.5.3



More information about the devel mailing list