mirror of
https://github.com/darlinghq/darling-openjdk.git
synced 2024-11-27 14:20:27 +00:00
8222825: ARM32 SIGILL issue on single core CPU (not supported PLDW instruction)
Reviewed-by: dholmes, dlong
This commit is contained in:
parent
993feb95ea
commit
989fa190a6
@ -4348,7 +4348,8 @@ instruct loadConD(regD dst, immD src, iRegP tmp) %{
|
||||
// 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 @@ instruct prefetchAlloc( memoryP mem ) %{
|
||||
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) %{
|
||||
|
@ -434,7 +434,9 @@ class Assembler : public AbstractAssembler {
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,7 @@ class VM_Version: public Abstract_VM_Version {
|
||||
friend class JVMCIVMStructs;
|
||||
|
||||
static bool _has_simd;
|
||||
static bool _has_mp_ext;
|
||||
|
||||
protected:
|
||||
// Are we done with vm version initialization
|
||||
@ -47,6 +48,7 @@ class VM_Version: public Abstract_VM_Version {
|
||||
vfp = 0,
|
||||
vfp3_32 = 1,
|
||||
simd = 2,
|
||||
mp_ext = 3
|
||||
};
|
||||
|
||||
enum Feature_Flag_Set {
|
||||
@ -56,6 +58,7 @@ class VM_Version: public Abstract_VM_Version {
|
||||
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 @@ class VM_Version: public Abstract_VM_Version {
|
||||
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; }
|
||||
|
||||
|
@ -40,6 +40,7 @@ extern "C" {
|
||||
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 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
|
||||
|
||||
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 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
|
||||
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 @@ void VM_Version::initialize() {
|
||||
#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 @@ void VM_Version::initialize() {
|
||||
&& _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);
|
||||
|
@ -248,11 +248,13 @@ frame os::current_frame() {
|
||||
|
||||
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 @@ extern "C" int JVM_handle_linux_signal(int sig, siginfo_t* info,
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user