1687 Race in determine_platform / get_hwenv causes multi-CPU VM hang at boot
authorMatt Amdur <mba@delphix.com>
Mon, 31 Oct 2011 06:14:21 -0700
changeset 13498 e702644ca141
parent 13497 205481e35e49
child 13499 cb9d7a417470
1687 Race in determine_platform / get_hwenv causes multi-CPU VM hang at boot Reviewed by: Adam Leventhal <[email protected]> Reviewed by: Eric Schrock <[email protected]> Reviewed by: Robert Mustacchi <[email protected]> Reviewed by: Garrett D'Amore <[email protected]> Approved by: Richard Lowe <[email protected]>
usr/src/uts/i86pc/os/cpuid.c
usr/src/uts/i86pc/os/mlsetup.c
usr/src/uts/intel/sys/x86_archext.h
--- a/usr/src/uts/i86pc/os/cpuid.c	Sat Oct 29 05:11:55 2011 +0400
+++ b/usr/src/uts/i86pc/os/cpuid.c	Mon Oct 31 06:14:21 2011 -0700
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011 by Delphix. All rights reserved.
  */
 /*
  * Copyright (c) 2010, Intel Corporation.
@@ -590,13 +591,22 @@
 
 #if !defined(__xpv)
 
-static void
-determine_platform()
+/*
+ * Determine the type of the underlying platform. This is used to customize
+ * initialization of various subsystems (e.g. TSC). determine_platform() must
+ * only ever be called once to prevent two processors from seeing different
+ * values of platform_type, it must be called before cpuid_pass1(), the
+ * earliest consumer to execute.
+ */
+void
+determine_platform(void)
 {
 	struct cpuid_regs cp;
 	char *xen_str;
 	uint32_t xen_signature[4], base;
 
+	ASSERT(platform_type == -1);
+
 	platform_type = HW_NATIVE;
 
 	if (!enable_platform_detection)
@@ -633,9 +643,7 @@
 int
 get_hwenv(void)
 {
-	if (platform_type == -1)
-		determine_platform();
-
+	ASSERT(platform_type != -1);
 	return (platform_type);
 }
 
@@ -870,9 +878,6 @@
 	extern int idle_cpu_prefer_mwait;
 #endif
 
-#if !defined(__xpv)
-	determine_platform();
-#endif
 	/*
 	 * Space statically allocated for BSP, ensure pointer is set
 	 */
--- a/usr/src/uts/i86pc/os/mlsetup.c	Sat Oct 29 05:11:55 2011 +0400
+++ b/usr/src/uts/i86pc/os/mlsetup.c	Mon Oct 31 06:14:21 2011 -0700
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011 by Delphix. All rights reserved.
  */
 /*
  * Copyright (c) 2010, Intel Corporation.
@@ -172,6 +173,11 @@
 		pci_cfgspace_init();
 #else
 	pci_cfgspace_init();
+	/*
+	 * Initialize the platform type from CPU 0 to ensure that
+	 * determine_platform() is only ever called once.
+	 */
+	determine_platform();
 #endif
 
 	/*
--- a/usr/src/uts/intel/sys/x86_archext.h	Sat Oct 29 05:11:55 2011 +0400
+++ b/usr/src/uts/intel/sys/x86_archext.h	Mon Oct 31 06:14:21 2011 -0700
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011 by Delphix. All rights reserved.
  */
 /*
  * Copyright (c) 2010, Intel Corporation.
@@ -762,6 +763,9 @@
 extern void patch_workaround_6323525(void);
 #endif
 
+#if !defined(__xpv)
+extern void determine_platform(void);
+#endif
 extern int get_hwenv(void);
 extern int is_controldom(void);