8194258: PPC64 safepoint mechanism: Fix initialization on AIX and support SIGTRAP
authormdoerr
Wed, 10 Jan 2018 11:09:55 +0100
changeset 48506 478e77658965
parent 48505 5db30620a3db
child 48507 282262d5031b
child 48508 5207db413697
8194258: PPC64 safepoint mechanism: Fix initialization on AIX and support SIGTRAP Summary: Use mmap on AIX to allocate protected page. Use trap instructions for polling if UseSIGTRAP is enabled. Reviewed-by: rehn, goetz
src/hotspot/cpu/ppc/globalDefinitions_ppc.hpp
src/hotspot/cpu/ppc/macroAssembler_ppc.inline.hpp
src/hotspot/cpu/ppc/nativeInst_ppc.hpp
src/hotspot/os/aix/safepointMechanism_aix.cpp
src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp
src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp
src/hotspot/share/runtime/safepointMechanism.cpp
test/hotspot/jtreg/runtime/logging/OsCpuLoggingTest.java
--- a/src/hotspot/cpu/ppc/globalDefinitions_ppc.hpp	Wed Jan 10 09:04:11 2018 +0100
+++ b/src/hotspot/cpu/ppc/globalDefinitions_ppc.hpp	Wed Jan 10 11:09:55 2018 +0100
@@ -55,5 +55,9 @@
 #define SUPPORT_RESERVED_STACK_AREA
 
 #define THREAD_LOCAL_POLL
+// If UseSIGTRAP is active, we only use the poll bit and no polling page.
+// Otherwise, we fall back to usage of the polling page in nmethods.
+// Define the condition to use this -XX flag.
+#define USE_POLL_BIT_ONLY UseSIGTRAP
 
 #endif // CPU_PPC_VM_GLOBALDEFINITIONS_PPC_HPP
--- a/src/hotspot/cpu/ppc/macroAssembler_ppc.inline.hpp	Wed Jan 10 09:04:11 2018 +0100
+++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.inline.hpp	Wed Jan 10 11:09:55 2018 +0100
@@ -30,6 +30,7 @@
 #include "asm/macroAssembler.hpp"
 #include "asm/codeBuffer.hpp"
 #include "code/codeCache.hpp"
+#include "runtime/safepointMechanism.hpp"
 
 inline bool MacroAssembler::is_ld_largeoffset(address a) {
   const int inst1 = *(int *)a;
@@ -261,7 +262,12 @@
 
 // Read from the polling page, its address is already in a register.
 inline void MacroAssembler::load_from_polling_page(Register polling_page_address, int offset) {
-  ld(R0, offset, polling_page_address);
+  if (SafepointMechanism::uses_thread_local_poll() && USE_POLL_BIT_ONLY) {
+    int encoding = SafepointMechanism::poll_bit();
+    tdi(traptoGreaterThanUnsigned | traptoEqual, polling_page_address, encoding);
+  } else {
+    ld(R0, offset, polling_page_address);
+  }
 }
 
 // Trap-instruction-based checks.
--- a/src/hotspot/cpu/ppc/nativeInst_ppc.hpp	Wed Jan 10 09:04:11 2018 +0100
+++ b/src/hotspot/cpu/ppc/nativeInst_ppc.hpp	Wed Jan 10 11:09:55 2018 +0100
@@ -31,6 +31,7 @@
 #include "memory/allocation.hpp"
 #include "runtime/icache.hpp"
 #include "runtime/os.hpp"
+#include "runtime/safepointMechanism.hpp"
 
 // We have interfaces for the following instructions:
 //
@@ -93,6 +94,11 @@
   bool is_safepoint_poll() {
     // Is the current instruction a POTENTIAL read access to the polling page?
     // The current arguments of the instruction are not checked!
+    if (SafepointMechanism::uses_thread_local_poll() && USE_POLL_BIT_ONLY) {
+      int encoding = SafepointMechanism::poll_bit();
+      return MacroAssembler::is_tdi(long_at(0), Assembler::traptoGreaterThanUnsigned | Assembler::traptoEqual,
+                                    -1, encoding);
+    }
     return MacroAssembler::is_load_from_polling_page(long_at(0), NULL);
   }
 
--- a/src/hotspot/os/aix/safepointMechanism_aix.cpp	Wed Jan 10 09:04:11 2018 +0100
+++ b/src/hotspot/os/aix/safepointMechanism_aix.cpp	Wed Jan 10 11:09:55 2018 +0100
@@ -30,8 +30,18 @@
 #include <sys/mman.h>
 
 void SafepointMechanism::pd_initialize() {
+  // No special code needed if we can use SIGTRAP
+  if (ThreadLocalHandshakes && USE_POLL_BIT_ONLY) {
+    default_initialize();
+    return;
+  }
+
+  // Allocate one protected page
   char* map_address = (char*)MAP_FAILED;
   const size_t page_size = os::vm_page_size();
+  const int prot  = PROT_READ;
+  const int flags = MAP_PRIVATE | MAP_ANONYMOUS;
+
   // Use optimized addresses for the polling page,
   // e.g. map it to a special 32-bit address.
   if (OptimizePollingPageLocation) {
@@ -57,14 +67,14 @@
       // Try to map with current address wish.
       // AIX: AIX needs MAP_FIXED if we provide an address and mmap will
       // fail if the address is already mapped.
-      map_address = (char*) ::mmap(address_wishes[i] - (ssize_t)page_size,
-                                   page_size, PROT_READ,
-                                   MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
+      map_address = (char*) ::mmap(address_wishes[i],
+                                   page_size, prot,
+                                   flags | MAP_FIXED,
                                    -1, 0);
-      log_debug(os)("SafePoint Polling  Page address: %p (wish) => %p",
-                    address_wishes[i], map_address + (ssize_t)page_size);
+      log_debug(os)("SafePoint Polling Page address: %p (wish) => %p",
+                    address_wishes[i], map_address);
 
-      if (map_address + (ssize_t)page_size == address_wishes[i]) {
+      if (map_address == address_wishes[i]) {
         // Map succeeded and map_address is at wished address, exit loop.
         break;
       }
@@ -78,8 +88,17 @@
     }
   }
   if (map_address == (char*)MAP_FAILED) {
-    map_address = os::reserve_memory(page_size, NULL, page_size);
+    map_address = (char*) ::mmap(NULL, page_size, prot, flags, -1, 0);
   }
   guarantee(map_address != (char*)MAP_FAILED, "SafepointMechanism::pd_initialize: failed to allocate polling page");
+  log_info(os)("SafePoint Polling address: " INTPTR_FORMAT, p2i(map_address));
   os::set_polling_page((address)(map_address));
+
+  // Use same page for ThreadLocalHandshakes without SIGTRAP
+  if (ThreadLocalHandshakes) {
+    set_uses_thread_local_poll();
+    intptr_t bad_page_val = reinterpret_cast<intptr_t>(map_address);
+    _poll_armed_value    = reinterpret_cast<void*>(bad_page_val | poll_bit());
+    _poll_disarmed_value = NULL; // Readable on AIX
+  }
 }
--- a/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp	Wed Jan 10 09:04:11 2018 +0100
+++ b/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp	Wed Jan 10 11:09:55 2018 +0100
@@ -47,6 +47,7 @@
 #include "runtime/javaCalls.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/osThread.hpp"
+#include "runtime/safepointMechanism.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/stubRoutines.hpp"
 #include "runtime/thread.inline.hpp"
@@ -374,9 +375,12 @@
         goto run_stub;
       }
 
-      else if (sig == SIGSEGV && os::is_poll_address(addr)) {
+      else if ((SafepointMechanism::uses_thread_local_poll() && USE_POLL_BIT_ONLY)
+               ? (sig == SIGTRAP && ((NativeInstruction*)pc)->is_safepoint_poll())
+               : (sig == SIGSEGV && os::is_poll_address(addr))) {
         if (TraceTraps) {
-          tty->print_cr("trap: safepoint_poll at " INTPTR_FORMAT " (SIGSEGV)", pc);
+          tty->print_cr("trap: safepoint_poll at " INTPTR_FORMAT " (%s)", p2i(pc),
+                        (SafepointMechanism::uses_thread_local_poll() && USE_POLL_BIT_ONLY) ? "SIGTRAP" : "SIGSEGV");
         }
         stub = SharedRuntime::get_poll_stub(pc);
         goto run_stub;
--- a/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp	Wed Jan 10 09:04:11 2018 +0100
+++ b/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp	Wed Jan 10 11:09:55 2018 +0100
@@ -46,6 +46,7 @@
 #include "runtime/javaCalls.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/osThread.hpp"
+#include "runtime/safepointMechanism.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/stubRoutines.hpp"
 #include "runtime/thread.inline.hpp"
@@ -382,7 +383,7 @@
         stub = SharedRuntime::get_handle_wrong_method_stub();
       }
 
-      else if (sig == SIGSEGV &&
+      else if (sig == ((SafepointMechanism::uses_thread_local_poll() && USE_POLL_BIT_ONLY) ? SIGTRAP : SIGSEGV) &&
                // A linux-ppc64 kernel before 2.6.6 doesn't set si_addr on some segfaults
                // in 64bit mode (cf. http://www.kernel.org/pub/linux/kernel/v2.6/ChangeLog-2.6.6),
                // especially when we try to read from the safepoint polling page. So the check
@@ -393,7 +394,8 @@
                ((cb = CodeCache::find_blob(pc)) != NULL) &&
                cb->is_compiled()) {
         if (TraceTraps) {
-          tty->print_cr("trap: safepoint_poll at " INTPTR_FORMAT " (SIGSEGV)", p2i(pc));
+          tty->print_cr("trap: safepoint_poll at " INTPTR_FORMAT " (%s)", p2i(pc),
+                        (SafepointMechanism::uses_thread_local_poll() && USE_POLL_BIT_ONLY) ? "SIGTRAP" : "SIGSEGV");
         }
         stub = SharedRuntime::get_poll_stub(pc);
       }
--- a/src/hotspot/share/runtime/safepointMechanism.cpp	Wed Jan 10 09:04:11 2018 +0100
+++ b/src/hotspot/share/runtime/safepointMechanism.cpp	Wed Jan 10 11:09:55 2018 +0100
@@ -36,23 +36,39 @@
 void SafepointMechanism::default_initialize() {
   if (ThreadLocalHandshakes) {
     set_uses_thread_local_poll();
-    const size_t page_size = os::vm_page_size();
-    const size_t allocation_size = 2 * page_size;
-    char* polling_page = os::reserve_memory(allocation_size, NULL, page_size);
-    os::commit_memory_or_exit(polling_page, allocation_size, false, "Unable to commit Safepoint polling page");
+
+    // Poll bit values
+    intptr_t poll_armed_value = poll_bit();
+    intptr_t poll_disarmed_value = 0;
 
-    char* bad_page  = polling_page;
-    char* good_page = polling_page + page_size;
+#ifdef USE_POLL_BIT_ONLY
+    if (!USE_POLL_BIT_ONLY)
+#endif
+    {
+      // Polling page
+      const size_t page_size = os::vm_page_size();
+      const size_t allocation_size = 2 * page_size;
+      char* polling_page = os::reserve_memory(allocation_size, NULL, page_size);
+      os::commit_memory_or_exit(polling_page, allocation_size, false, "Unable to commit Safepoint polling page");
 
-    os::protect_memory(bad_page, page_size, os::MEM_PROT_NONE);
-    os::protect_memory(good_page, page_size, os::MEM_PROT_READ);
+      char* bad_page  = polling_page;
+      char* good_page = polling_page + page_size;
+
+      os::protect_memory(bad_page,  page_size, os::MEM_PROT_NONE);
+      os::protect_memory(good_page, page_size, os::MEM_PROT_READ);
+
+      log_info(os)("SafePoint Polling address, bad (protected) page:" INTPTR_FORMAT ", good (unprotected) page:" INTPTR_FORMAT, p2i(bad_page), p2i(good_page));
+      os::set_polling_page((address)(bad_page));
 
-    log_info(os)("SafePoint Polling address, bad (protected) page:" INTPTR_FORMAT ", good (unprotected) page:" INTPTR_FORMAT, p2i(bad_page), p2i(good_page));
-    os::set_polling_page((address)(bad_page));
+      // Poll address values
+      intptr_t bad_page_val  = reinterpret_cast<intptr_t>(bad_page),
+               good_page_val = reinterpret_cast<intptr_t>(good_page);
+      poll_armed_value    |= bad_page_val;
+      poll_disarmed_value |= good_page_val;
+    }
 
-    intptr_t poll_page_val = reinterpret_cast<intptr_t>(bad_page);
-    _poll_armed_value = reinterpret_cast<void*>(poll_page_val | poll_bit());
-    _poll_disarmed_value = good_page;
+    _poll_armed_value    = reinterpret_cast<void*>(poll_armed_value);
+    _poll_disarmed_value = reinterpret_cast<void*>(poll_disarmed_value);
   } else {
     const size_t page_size = os::vm_page_size();
     char* polling_page = os::reserve_memory(page_size, NULL, page_size);
--- a/test/hotspot/jtreg/runtime/logging/OsCpuLoggingTest.java	Wed Jan 10 09:04:11 2018 +0100
+++ b/test/hotspot/jtreg/runtime/logging/OsCpuLoggingTest.java	Wed Jan 10 11:09:55 2018 +0100
@@ -40,10 +40,7 @@
 public class OsCpuLoggingTest {
 
     static void analyzeOutputForOsLog(OutputAnalyzer output) throws Exception {
-        // Aix has it's own logging
-        if (!Platform.isAix()) {
-            output.shouldContain("SafePoint Polling address");
-        }
+        output.shouldContain("SafePoint Polling address");
         output.shouldHaveExitValue(0);
     }
 
@@ -58,7 +55,10 @@
         OutputAnalyzer output = new OutputAnalyzer(pb.start());
         analyzeOutputForOsCpuLog(output);
 
-        pb = ProcessTools.createJavaProcessBuilder("-Xlog:os", "-version");
+        // PPC64 only uses polling pages when UseSIGTRAP is off.
+        pb = (Platform.isPPC() && Platform.is64bit())
+             ? ProcessTools.createJavaProcessBuilder("-Xlog:os", "-XX:-UseSIGTRAP", "-version")
+             : ProcessTools.createJavaProcessBuilder("-Xlog:os", "-version");
         output = new OutputAnalyzer(pb.start());
         analyzeOutputForOsLog(output);
     }