Skip to content

Commit 989fa19

Browse files
author
Boris Ulasevich
committed
8222825: ARM32 SIGILL issue on single core CPU (not supported PLDW instruction)
Reviewed-by: dholmes, dlong
1 parent 993feb9 commit 989fa19

File tree

5 files changed

+54
-6
lines changed

5 files changed

+54
-6
lines changed

src/hotspot/cpu/arm/arm.ad

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4348,7 +4348,8 @@ instruct loadConD(regD dst, immD src, iRegP tmp) %{
43484348
// Prefetch instructions.
43494349
// Must be safe to execute with invalid address (cannot fault).
43504350

4351-
instruct prefetchAlloc( memoryP mem ) %{
4351+
instruct prefetchAlloc_mp( memoryP mem ) %{
4352+
predicate(VM_Version::has_multiprocessing_extensions());
43524353
match( PrefetchAllocation mem );
43534354
ins_cost(MEMORY_REF_COST);
43544355
size(4);
@@ -4360,6 +4361,20 @@ instruct prefetchAlloc( memoryP mem ) %{
43604361
ins_pipe(iload_mem);
43614362
%}
43624363

4364+
instruct prefetchAlloc_sp( memoryP mem ) %{
4365+
predicate(!VM_Version::has_multiprocessing_extensions());
4366+
match( PrefetchAllocation mem );
4367+
ins_cost(MEMORY_REF_COST);
4368+
size(4);
4369+
4370+
format %{ "PLD $mem\t! Prefetch allocation" %}
4371+
ins_encode %{
4372+
__ pld($mem$$Address);
4373+
%}
4374+
ins_pipe(iload_mem);
4375+
%}
4376+
4377+
43634378
//----------Store Instructions-------------------------------------------------
43644379
// Store Byte
43654380
instruct storeB(memoryB mem, store_RegI src) %{

src/hotspot/cpu/arm/assembler_arm_32.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,9 @@ class Assembler : public AbstractAssembler {
434434
}
435435

436436
void pldw(Address addr) {
437-
assert(VM_Version::arm_arch() >= 7 && os::is_MP(), "no pldw on this processor");
437+
assert(!VM_Version::is_initialized() ||
438+
(VM_Version::arm_arch() >= 7 && VM_Version::has_multiprocessing_extensions()),
439+
"PLDW is available on ARMv7 with Multiprocessing Extensions only");
438440
emit_int32(0xf510f000 | addr.encoding2());
439441
}
440442

src/hotspot/cpu/arm/vm_version_arm.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class VM_Version: public Abstract_VM_Version {
3232
friend class JVMCIVMStructs;
3333

3434
static bool _has_simd;
35+
static bool _has_mp_ext;
3536

3637
protected:
3738
// Are we done with vm version initialization
@@ -47,6 +48,7 @@ class VM_Version: public Abstract_VM_Version {
4748
vfp = 0,
4849
vfp3_32 = 1,
4950
simd = 2,
51+
mp_ext = 3
5052
};
5153

5254
enum Feature_Flag_Set {
@@ -56,6 +58,7 @@ class VM_Version: public Abstract_VM_Version {
5658
vfp_m = 1 << vfp,
5759
vfp3_32_m = 1 << vfp3_32,
5860
simd_m = 1 << simd,
61+
mp_ext_m = 1 << mp_ext
5962
};
6063

6164
// The value stored by "STR PC, [addr]" instruction can be either
@@ -97,6 +100,7 @@ class VM_Version: public Abstract_VM_Version {
97100
static bool has_vfp() { return (_features & vfp_m) != 0; }
98101
static bool has_vfp3_32() { return (_features & vfp3_32_m) != 0; }
99102
static bool has_simd() { return (_features & simd_m) != 0; }
103+
static bool has_multiprocessing_extensions() { return (_features & mp_ext_m) != 0; }
100104

101105
static bool simd_math_is_compliant() { return false; }
102106

src/hotspot/cpu/arm/vm_version_arm_32.cpp

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ extern "C" {
4040
typedef int (*get_cpu_info_t)();
4141
typedef bool (*check_vfp_t)(double *d);
4242
typedef bool (*check_simd_t)();
43+
typedef bool (*check_mp_ext_t)(int *addr);
4344
}
4445

4546
#define __ _masm->
@@ -95,6 +96,20 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
9596

9697
return start;
9798
};
99+
100+
address generate_check_mp_ext() {
101+
StubCodeMark mark(this, "VM_Version", "check_mp_ext");
102+
address start = __ pc();
103+
104+
// PLDW is available with Multiprocessing Extensions only
105+
__ pldw(Address(R0));
106+
// Return true if instruction caused no signals
107+
__ mov(R0, 1);
108+
// JVM_handle_linux_signal moves PC here if SIGILL happens
109+
__ bx(LR);
110+
111+
return start;
112+
};
98113
};
99114

100115
#undef __
@@ -103,6 +118,7 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
103118
extern "C" address check_vfp3_32_fault_instr;
104119
extern "C" address check_vfp_fault_instr;
105120
extern "C" address check_simd_fault_instr;
121+
extern "C" address check_mp_ext_fault_instr;
106122

107123
void VM_Version::early_initialize() {
108124

@@ -165,6 +181,13 @@ void VM_Version::initialize() {
165181
#endif
166182
#endif
167183

184+
address check_mp_ext_pc = g.generate_check_mp_ext();
185+
check_mp_ext_t check_mp_ext = CAST_TO_FN_PTR(check_mp_ext_t, check_mp_ext_pc);
186+
check_mp_ext_fault_instr = (address)check_mp_ext;
187+
int dummy_local_variable;
188+
if (check_mp_ext(&dummy_local_variable)) {
189+
_features |= mp_ext_m;
190+
}
168191

169192
if (UseAESIntrinsics && !FLAG_IS_DEFAULT(UseAESIntrinsics)) {
170193
warning("AES intrinsics are not available on this CPU");
@@ -247,11 +270,12 @@ void VM_Version::initialize() {
247270
&& _supports_atomic_getset8 && _supports_atomic_getadd8, "C2: atomic operations must be supported");
248271
#endif
249272
char buf[512];
250-
jio_snprintf(buf, sizeof(buf), "(ARMv%d)%s%s%s",
273+
jio_snprintf(buf, sizeof(buf), "(ARMv%d)%s%s%s%s",
251274
_arm_arch,
252275
(has_vfp() ? ", vfp" : ""),
253276
(has_vfp3_32() ? ", vfp3-32" : ""),
254-
(has_simd() ? ", simd" : ""));
277+
(has_simd() ? ", simd" : ""),
278+
(has_multiprocessing_extensions() ? ", mp_ext" : ""));
255279

256280
// buf is started with ", " or is empty
257281
_features_string = os::strdup(buf);

src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,11 +248,13 @@ frame os::current_frame() {
248248

249249
extern "C" address check_vfp_fault_instr;
250250
extern "C" address check_vfp3_32_fault_instr;
251+
extern "C" address check_simd_fault_instr;
252+
extern "C" address check_mp_ext_fault_instr;
251253

252254
address check_vfp_fault_instr = NULL;
253255
address check_vfp3_32_fault_instr = NULL;
254-
extern "C" address check_simd_fault_instr;
255256
address check_simd_fault_instr = NULL;
257+
address check_mp_ext_fault_instr = NULL;
256258

257259
// Utility functions
258260

@@ -271,7 +273,8 @@ extern "C" int JVM_handle_linux_signal(int sig, siginfo_t* info,
271273
if (sig == SIGILL &&
272274
((info->si_addr == (caddr_t)check_simd_fault_instr)
273275
|| info->si_addr == (caddr_t)check_vfp_fault_instr
274-
|| info->si_addr == (caddr_t)check_vfp3_32_fault_instr)) {
276+
|| info->si_addr == (caddr_t)check_vfp3_32_fault_instr
277+
|| info->si_addr == (caddr_t)check_mp_ext_fault_instr)) {
275278
// skip faulty instruction + instruction that sets return value to
276279
// success and set return value to failure.
277280
os::Linux::ucontext_set_pc(uc, (address)info->si_addr + 8);

0 commit comments

Comments
 (0)