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
--- 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);
}