From 77d38feb95ceb6f8cd968909778c0b87aa1545c4 Mon Sep 17 00:00:00 2001
From: Vladimir Kozlov <kvn@openjdk.org>
Date: Mon, 31 Mar 2014 13:08:03 -0700
Subject: [PATCH] 8038633: crash in VM_Version::get_processor_features() on
 startup

Windows need an exception wrapper around getPsrInfo_stub() call in order to properly handle SEGV for YMM registers test.

Reviewed-by: iveresov, iignatyev
---
 hotspot/src/cpu/x86/vm/vm_version_x86.cpp     | 32 +++++++++++++------
 hotspot/src/cpu/x86/vm/vm_version_x86.hpp     |  1 +
 hotspot/src/os/windows/vm/os_windows.cpp      |  2 --
 hotspot/src/os/windows/vm/os_windows.hpp      |  2 --
 .../src/os/windows/vm/os_windows.inline.hpp   |  6 ++--
 hotspot/src/share/vm/prims/jni.cpp            |  2 +-
 6 files changed, 26 insertions(+), 19 deletions(-)

diff --git a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp
index 28b79b784f2..ba5fcb383c6 100644
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp
@@ -59,9 +59,9 @@ static BufferBlob* stub_blob;
 static const int stub_size = 600;
 
 extern "C" {
-  typedef void (*getPsrInfo_stub_t)(void*);
+  typedef void (*get_cpu_info_stub_t)(void*);
 }
-static getPsrInfo_stub_t getPsrInfo_stub = NULL;
+static get_cpu_info_stub_t get_cpu_info_stub = NULL;
 
 
 class VM_Version_StubGenerator: public StubCodeGenerator {
@@ -69,7 +69,7 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
 
   VM_Version_StubGenerator(CodeBuffer *c) : StubCodeGenerator(c) {}
 
-  address generate_getPsrInfo() {
+  address generate_get_cpu_info() {
     // Flags to test CPU type.
     const uint32_t HS_EFL_AC           = 0x40000;
     const uint32_t HS_EFL_ID           = 0x200000;
@@ -81,13 +81,13 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
     Label detect_486, cpu486, detect_586, std_cpuid1, std_cpuid4;
     Label sef_cpuid, ext_cpuid, ext_cpuid1, ext_cpuid5, ext_cpuid7, done;
 
-    StubCodeMark mark(this, "VM_Version", "getPsrInfo_stub");
+    StubCodeMark mark(this, "VM_Version", "get_cpu_info_stub");
 #   define __ _masm->
 
     address start = __ pc();
 
     //
-    // void getPsrInfo(VM_Version::CpuidInfo* cpuid_info);
+    // void get_cpu_info(VM_Version::CpuidInfo* cpuid_info);
     //
     // LP64: rcx and rdx are first and second argument registers on windows
 
@@ -385,6 +385,14 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
 };
 
 
+void VM_Version::get_cpu_info_wrapper() {
+  get_cpu_info_stub(&_cpuid_info);
+}
+
+#ifndef CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED
+  #define CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(f) f()
+#endif
+
 void VM_Version::get_processor_features() {
 
   _cpu = 4; // 486 by default
@@ -395,7 +403,11 @@ void VM_Version::get_processor_features() {
 
   if (!Use486InstrsOnly) {
     // Get raw processor info
-    getPsrInfo_stub(&_cpuid_info);
+
+    // Some platforms (like Win*) need a wrapper around here
+    // in order to properly handle SEGV for YMM registers test.
+    CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(get_cpu_info_wrapper);
+
     assert_is_initialized();
     _cpu = extended_cpu_family();
     _model = extended_cpu_model();
@@ -986,14 +998,14 @@ void VM_Version::initialize() {
   ResourceMark rm;
   // Making this stub must be FIRST use of assembler
 
-  stub_blob = BufferBlob::create("getPsrInfo_stub", stub_size);
+  stub_blob = BufferBlob::create("get_cpu_info_stub", stub_size);
   if (stub_blob == NULL) {
-    vm_exit_during_initialization("Unable to allocate getPsrInfo_stub");
+    vm_exit_during_initialization("Unable to allocate get_cpu_info_stub");
   }
   CodeBuffer c(stub_blob);
   VM_Version_StubGenerator g(&c);
-  getPsrInfo_stub = CAST_TO_FN_PTR(getPsrInfo_stub_t,
-                                   g.generate_getPsrInfo());
+  get_cpu_info_stub = CAST_TO_FN_PTR(get_cpu_info_stub_t,
+                                     g.generate_get_cpu_info());
 
   get_processor_features();
 }
diff --git a/hotspot/src/cpu/x86/vm/vm_version_x86.hpp b/hotspot/src/cpu/x86/vm/vm_version_x86.hpp
index a3be0995ae1..51f6e4f2f4a 100644
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.hpp
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.hpp
@@ -507,6 +507,7 @@ public:
   // The value used to check ymm register after signal handle
   static int ymm_test_value()    { return 0xCAFEBABE; }
 
+  static void get_cpu_info_wrapper();
   static void set_cpuinfo_segv_addr(address pc) { _cpuinfo_segv_addr = pc; }
   static bool  is_cpuinfo_segv_addr(address pc) { return _cpuinfo_segv_addr == pc; }
   static void set_cpuinfo_cont_addr(address pc) { _cpuinfo_cont_addr = pc; }
diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp
index 1f4e12c132c..9f0f8a40ca6 100644
--- a/hotspot/src/os/windows/vm/os_windows.cpp
+++ b/hotspot/src/os/windows/vm/os_windows.cpp
@@ -2702,7 +2702,6 @@ address os::win32::fast_jni_accessor_wrapper(BasicType type) {
 }
 #endif
 
-#ifndef PRODUCT
 void os::win32::call_test_func_with_wrapper(void (*funcPtr)(void)) {
   // Install a win32 structured exception handler around the test
   // function call so the VM can generate an error dump if needed.
@@ -2713,7 +2712,6 @@ void os::win32::call_test_func_with_wrapper(void (*funcPtr)(void)) {
     // Nothing to do.
   }
 }
-#endif
 
 // Virtual Memory
 
diff --git a/hotspot/src/os/windows/vm/os_windows.hpp b/hotspot/src/os/windows/vm/os_windows.hpp
index eaf751ec561..f3ea83d8242 100644
--- a/hotspot/src/os/windows/vm/os_windows.hpp
+++ b/hotspot/src/os/windows/vm/os_windows.hpp
@@ -101,9 +101,7 @@ class win32 {
   static address fast_jni_accessor_wrapper(BasicType);
 #endif
 
-#ifndef PRODUCT
   static void call_test_func_with_wrapper(void (*funcPtr)(void));
-#endif
 
   // filter function to ignore faults on serializations page
   static LONG WINAPI serialize_fault_filter(struct _EXCEPTION_POINTERS* e);
diff --git a/hotspot/src/os/windows/vm/os_windows.inline.hpp b/hotspot/src/os/windows/vm/os_windows.inline.hpp
index a6d20d90b33..f014fc9eb56 100644
--- a/hotspot/src/os/windows/vm/os_windows.inline.hpp
+++ b/hotspot/src/os/windows/vm/os_windows.inline.hpp
@@ -111,9 +111,7 @@ inline bool os::supports_monotonic_clock() {
   return win32::_has_performance_count;
 }
 
-#ifndef PRODUCT
-  #define CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(f) \
-            os::win32::call_test_func_with_wrapper(f)
-#endif
+#define CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(f) \
+        os::win32::call_test_func_with_wrapper(f)
 
 #endif // OS_WINDOWS_VM_OS_WINDOWS_INLINE_HPP
diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp
index 3f06633e612..c3d588fd4c6 100644
--- a/hotspot/src/share/vm/prims/jni.cpp
+++ b/hotspot/src/share/vm/prims/jni.cpp
@@ -4001,7 +4001,7 @@ _JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_CreateJavaVM(JavaVM **vm, void **penv, v
     }
 
 #ifndef PRODUCT
-  #ifndef TARGET_OS_FAMILY_windows
+  #ifndef CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED
     #define CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(f) f()
   #endif