8222825: ARM32 SIGILL issue on single core CPU (not supported PLDW instruction)
Reviewed-by: dholmes, dlong
--- a/src/hotspot/cpu/arm/arm.ad Fri May 17 00:21:10 2019 +0200
+++ b/src/hotspot/cpu/arm/arm.ad Thu May 16 18:45:30 2019 -0400
@@ -4348,7 +4348,8 @@
// Prefetch instructions.
// Must be safe to execute with invalid address (cannot fault).
-instruct prefetchAlloc( memoryP mem ) %{
+instruct prefetchAlloc_mp( memoryP mem ) %{
+ predicate(VM_Version::has_multiprocessing_extensions());
match( PrefetchAllocation mem );
ins_cost(MEMORY_REF_COST);
size(4);
@@ -4360,6 +4361,20 @@
ins_pipe(iload_mem);
%}
+instruct prefetchAlloc_sp( memoryP mem ) %{
+ predicate(!VM_Version::has_multiprocessing_extensions());
+ match( PrefetchAllocation mem );
+ ins_cost(MEMORY_REF_COST);
+ size(4);
+
+ format %{ "PLD $mem\t! Prefetch allocation" %}
+ ins_encode %{
+ __ pld($mem$$Address);
+ %}
+ ins_pipe(iload_mem);
+%}
+
+
//----------Store Instructions-------------------------------------------------
// Store Byte
instruct storeB(memoryB mem, store_RegI src) %{
--- a/src/hotspot/cpu/arm/assembler_arm_32.hpp Fri May 17 00:21:10 2019 +0200
+++ b/src/hotspot/cpu/arm/assembler_arm_32.hpp Thu May 16 18:45:30 2019 -0400
@@ -434,7 +434,9 @@
}
void pldw(Address addr) {
- assert(VM_Version::arm_arch() >= 7 && os::is_MP(), "no pldw on this processor");
+ assert(!VM_Version::is_initialized() ||
+ (VM_Version::arm_arch() >= 7 && VM_Version::has_multiprocessing_extensions()),
+ "PLDW is available on ARMv7 with Multiprocessing Extensions only");
emit_int32(0xf510f000 | addr.encoding2());
}
--- a/src/hotspot/cpu/arm/vm_version_arm.hpp Fri May 17 00:21:10 2019 +0200
+++ b/src/hotspot/cpu/arm/vm_version_arm.hpp Thu May 16 18:45:30 2019 -0400
@@ -32,6 +32,7 @@
friend class JVMCIVMStructs;
static bool _has_simd;
+ static bool _has_mp_ext;
protected:
// Are we done with vm version initialization
@@ -47,6 +48,7 @@
vfp = 0,
vfp3_32 = 1,
simd = 2,
+ mp_ext = 3
};
enum Feature_Flag_Set {
@@ -56,6 +58,7 @@
vfp_m = 1 << vfp,
vfp3_32_m = 1 << vfp3_32,
simd_m = 1 << simd,
+ mp_ext_m = 1 << mp_ext
};
// The value stored by "STR PC, [addr]" instruction can be either
@@ -97,6 +100,7 @@
static bool has_vfp() { return (_features & vfp_m) != 0; }
static bool has_vfp3_32() { return (_features & vfp3_32_m) != 0; }
static bool has_simd() { return (_features & simd_m) != 0; }
+ static bool has_multiprocessing_extensions() { return (_features & mp_ext_m) != 0; }
static bool simd_math_is_compliant() { return false; }
--- a/src/hotspot/cpu/arm/vm_version_arm_32.cpp Fri May 17 00:21:10 2019 +0200
+++ b/src/hotspot/cpu/arm/vm_version_arm_32.cpp Thu May 16 18:45:30 2019 -0400
@@ -40,6 +40,7 @@
typedef int (*get_cpu_info_t)();
typedef bool (*check_vfp_t)(double *d);
typedef bool (*check_simd_t)();
+ typedef bool (*check_mp_ext_t)(int *addr);
}
#define __ _masm->
@@ -95,6 +96,20 @@
return start;
};
+
+ address generate_check_mp_ext() {
+ StubCodeMark mark(this, "VM_Version", "check_mp_ext");
+ address start = __ pc();
+
+ // PLDW is available with Multiprocessing Extensions only
+ __ pldw(Address(R0));
+ // Return true if instruction caused no signals
+ __ mov(R0, 1);
+ // JVM_handle_linux_signal moves PC here if SIGILL happens
+ __ bx(LR);
+
+ return start;
+ };
};
#undef __
@@ -103,6 +118,7 @@
extern "C" address check_vfp3_32_fault_instr;
extern "C" address check_vfp_fault_instr;
extern "C" address check_simd_fault_instr;
+extern "C" address check_mp_ext_fault_instr;
void VM_Version::early_initialize() {
@@ -165,6 +181,13 @@
#endif
#endif
+ address check_mp_ext_pc = g.generate_check_mp_ext();
+ check_mp_ext_t check_mp_ext = CAST_TO_FN_PTR(check_mp_ext_t, check_mp_ext_pc);
+ check_mp_ext_fault_instr = (address)check_mp_ext;
+ int dummy_local_variable;
+ if (check_mp_ext(&dummy_local_variable)) {
+ _features |= mp_ext_m;
+ }
if (UseAESIntrinsics && !FLAG_IS_DEFAULT(UseAESIntrinsics)) {
warning("AES intrinsics are not available on this CPU");
@@ -247,11 +270,12 @@
&& _supports_atomic_getset8 && _supports_atomic_getadd8, "C2: atomic operations must be supported");
#endif
char buf[512];
- jio_snprintf(buf, sizeof(buf), "(ARMv%d)%s%s%s",
+ jio_snprintf(buf, sizeof(buf), "(ARMv%d)%s%s%s%s",
_arm_arch,
(has_vfp() ? ", vfp" : ""),
(has_vfp3_32() ? ", vfp3-32" : ""),
- (has_simd() ? ", simd" : ""));
+ (has_simd() ? ", simd" : ""),
+ (has_multiprocessing_extensions() ? ", mp_ext" : ""));
// buf is started with ", " or is empty
_features_string = os::strdup(buf);
--- a/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp Fri May 17 00:21:10 2019 +0200
+++ b/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp Thu May 16 18:45:30 2019 -0400
@@ -248,11 +248,13 @@
extern "C" address check_vfp_fault_instr;
extern "C" address check_vfp3_32_fault_instr;
+extern "C" address check_simd_fault_instr;
+extern "C" address check_mp_ext_fault_instr;
address check_vfp_fault_instr = NULL;
address check_vfp3_32_fault_instr = NULL;
-extern "C" address check_simd_fault_instr;
address check_simd_fault_instr = NULL;
+address check_mp_ext_fault_instr = NULL;
// Utility functions
@@ -271,7 +273,8 @@
if (sig == SIGILL &&
((info->si_addr == (caddr_t)check_simd_fault_instr)
|| info->si_addr == (caddr_t)check_vfp_fault_instr
- || info->si_addr == (caddr_t)check_vfp3_32_fault_instr)) {
+ || info->si_addr == (caddr_t)check_vfp3_32_fault_instr
+ || info->si_addr == (caddr_t)check_mp_ext_fault_instr)) {
// skip faulty instruction + instruction that sets return value to
// success and set return value to failure.
os::Linux::ucontext_set_pc(uc, (address)info->si_addr + 8);