diff options
Diffstat (limited to 'chromium/v8/src/execution/arm64')
5 files changed, 87 insertions, 29 deletions
diff --git a/chromium/v8/src/execution/arm64/pointer-auth-arm64.cc b/chromium/v8/src/execution/arm64/pointer-auth-arm64.cc index 36e792b752e..eaa88445ec2 100644 --- a/chromium/v8/src/execution/arm64/pointer-auth-arm64.cc +++ b/chromium/v8/src/execution/arm64/pointer-auth-arm64.cc @@ -10,8 +10,8 @@ namespace v8 { namespace internal { // Randomly generated example key for simulating only. -const Simulator::PACKey Simulator::kPACKeyIA = {0xc31718727de20f71, - 0xab9fd4e14b2fec51, 0}; +const Simulator::PACKey Simulator::kPACKeyIB = {0xeebb163b474e04c8, + 0x5267ac6fc280fb7c, 1}; namespace { diff --git a/chromium/v8/src/execution/arm64/pointer-authentication-arm64.h b/chromium/v8/src/execution/arm64/pointer-authentication-arm64.h index c54a59f29c7..e4bc476b3d0 100644 --- a/chromium/v8/src/execution/arm64/pointer-authentication-arm64.h +++ b/chromium/v8/src/execution/arm64/pointer-authentication-arm64.h @@ -10,11 +10,6 @@ #include "src/common/globals.h" #include "src/execution/arm64/simulator-arm64.h" -// TODO(v8:10026): Replace hints with instruction aliases, when supported. -#define AUTIA1716 "hint #12" -#define PACIA1716 "hint #8" -#define XPACLRI "hint #7" - namespace v8 { namespace internal { @@ -31,13 +26,13 @@ V8_INLINE Address PointerAuthentication::AuthenticatePC( uint64_t sp = reinterpret_cast<uint64_t>(pc_address) + offset_from_sp; uint64_t pc = reinterpret_cast<uint64_t>(*pc_address); #ifdef USE_SIMULATOR - pc = Simulator::AuthPAC(pc, sp, Simulator::kPACKeyIA, + pc = Simulator::AuthPAC(pc, sp, Simulator::kPACKeyIB, Simulator::kInstructionPointer); #else asm volatile( " mov x17, %[pc]\n" " mov x16, %[stack_ptr]\n" - " " AUTIA1716 "\n" + " autib1716\n" " ldr xzr, [x17]\n" " mov %[pc], x17\n" : [pc] "+r"(pc) @@ -55,7 +50,7 @@ V8_INLINE Address PointerAuthentication::StripPAC(Address pc) { asm volatile( " mov x16, lr\n" " mov lr, %[pc]\n" - " " XPACLRI "\n" + " xpaclri\n" " mov %[pc], lr\n" " mov lr, x16\n" : [pc] "+r"(pc) @@ -68,13 +63,13 @@ V8_INLINE Address PointerAuthentication::StripPAC(Address pc) { // Sign {pc} using {sp}. V8_INLINE Address PointerAuthentication::SignPCWithSP(Address pc, Address sp) { #ifdef USE_SIMULATOR - return Simulator::AddPAC(pc, sp, Simulator::kPACKeyIA, + return Simulator::AddPAC(pc, sp, Simulator::kPACKeyIB, Simulator::kInstructionPointer); #else asm volatile( " mov x17, %[pc]\n" " mov x16, %[sp]\n" - " " PACIA1716 "\n" + " pacib1716\n" " mov %[pc], x17\n" : [pc] "+r"(pc) : [sp] "r"(sp) @@ -92,13 +87,13 @@ V8_INLINE void PointerAuthentication::ReplacePC(Address* pc_address, uint64_t sp = reinterpret_cast<uint64_t>(pc_address) + offset_from_sp; uint64_t old_pc = reinterpret_cast<uint64_t>(*pc_address); #ifdef USE_SIMULATOR - uint64_t auth_old_pc = Simulator::AuthPAC(old_pc, sp, Simulator::kPACKeyIA, + uint64_t auth_old_pc = Simulator::AuthPAC(old_pc, sp, Simulator::kPACKeyIB, Simulator::kInstructionPointer); uint64_t raw_old_pc = Simulator::StripPAC(old_pc, Simulator::kInstructionPointer); // Verify that the old address is authenticated. CHECK_EQ(auth_old_pc, raw_old_pc); - new_pc = Simulator::AddPAC(new_pc, sp, Simulator::kPACKeyIA, + new_pc = Simulator::AddPAC(new_pc, sp, Simulator::kPACKeyIB, Simulator::kInstructionPointer); #else // Only store newly signed address after we have verified that the old @@ -106,10 +101,10 @@ V8_INLINE void PointerAuthentication::ReplacePC(Address* pc_address, asm volatile( " mov x17, %[new_pc]\n" " mov x16, %[sp]\n" - " " PACIA1716 "\n" + " pacib1716\n" " mov %[new_pc], x17\n" " mov x17, %[old_pc]\n" - " " AUTIA1716 "\n" + " autib1716\n" " ldr xzr, [x17]\n" : [new_pc] "+&r"(new_pc) : [sp] "r"(sp), [old_pc] "r"(old_pc) @@ -127,13 +122,13 @@ V8_INLINE void PointerAuthentication::ReplaceContext(Address* pc_address, uint64_t new_pc; #ifdef USE_SIMULATOR uint64_t auth_pc = - Simulator::AuthPAC(old_signed_pc, old_context, Simulator::kPACKeyIA, + Simulator::AuthPAC(old_signed_pc, old_context, Simulator::kPACKeyIB, Simulator::kInstructionPointer); uint64_t raw_pc = Simulator::StripPAC(auth_pc, Simulator::kInstructionPointer); // Verify that the old address is authenticated. CHECK_EQ(raw_pc, auth_pc); - new_pc = Simulator::AddPAC(raw_pc, new_context, Simulator::kPACKeyIA, + new_pc = Simulator::AddPAC(raw_pc, new_context, Simulator::kPACKeyIB, Simulator::kInstructionPointer); #else // Only store newly signed address after we have verified that the old @@ -141,13 +136,13 @@ V8_INLINE void PointerAuthentication::ReplaceContext(Address* pc_address, asm volatile( " mov x17, %[old_pc]\n" " mov x16, %[old_ctx]\n" - " " AUTIA1716 "\n" + " autib1716\n" " mov x16, %[new_ctx]\n" - " " PACIA1716 "\n" + " pacib1716\n" " mov %[new_pc], x17\n" " mov x17, %[old_pc]\n" " mov x16, %[old_ctx]\n" - " " AUTIA1716 "\n" + " autib1716\n" " ldr xzr, [x17]\n" : [new_pc] "=&r"(new_pc) : [old_pc] "r"(old_signed_pc), [old_ctx] "r"(old_context), diff --git a/chromium/v8/src/execution/arm64/simulator-arm64.cc b/chromium/v8/src/execution/arm64/simulator-arm64.cc index adc856a6066..4d9205f0537 100644 --- a/chromium/v8/src/execution/arm64/simulator-arm64.cc +++ b/chromium/v8/src/execution/arm64/simulator-arm64.cc @@ -445,7 +445,7 @@ using SimulatorRuntimeDirectGetterCall = void (*)(int64_t arg0, int64_t arg1); using SimulatorRuntimeProfilingGetterCall = void (*)(int64_t arg0, int64_t arg1, void* arg2); -// Separate for fine-grained UBSan blacklisting. Casting any given C++ +// Separate for fine-grained UBSan blocklisting. Casting any given C++ // function to {SimulatorRuntimeCall} is undefined behavior; but since // the target function can indeed be any function that's exposed via // the "fast C call" mechanism, we can't reconstruct its signature here. @@ -2756,6 +2756,9 @@ void Simulator::VisitFPIntegerConvert(Instruction* instr) { case FCVTZU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPZero)); break; + case FJCVTZS: + set_wreg(dst, FPToFixedJS(dreg(src))); + break; case FMOV_ws: set_wreg(dst, sreg_bits(src)); break; @@ -3125,8 +3128,8 @@ bool Simulator::FPProcessNaNs(Instruction* instr) { // clang-format off #define PAUTH_SYSTEM_MODES(V) \ - V(A1716, 17, xreg(16), kPACKeyIA) \ - V(ASP, 30, xreg(31, Reg31IsStackPointer), kPACKeyIA) + V(B1716, 17, xreg(16), kPACKeyIB) \ + V(BSP, 30, xreg(31, Reg31IsStackPointer), kPACKeyIB) // clang-format on void Simulator::VisitSystem(Instruction* instr) { @@ -3134,7 +3137,7 @@ void Simulator::VisitSystem(Instruction* instr) { // range of immediates instead of indicating a different instruction. This // makes the decoding tricky. if (instr->Mask(SystemPAuthFMask) == SystemPAuthFixed) { - // The BType check for PACIASP happens in CheckBType(). + // The BType check for PACIBSP happens in CheckBType(). switch (instr->Mask(SystemPAuthMask)) { #define DEFINE_PAUTH_FUNCS(SUFFIX, DST, MOD, KEY) \ case PACI##SUFFIX: \ diff --git a/chromium/v8/src/execution/arm64/simulator-arm64.h b/chromium/v8/src/execution/arm64/simulator-arm64.h index cd4137c8e51..ee6d6341825 100644 --- a/chromium/v8/src/execution/arm64/simulator-arm64.h +++ b/chromium/v8/src/execution/arm64/simulator-arm64.h @@ -828,8 +828,8 @@ class Simulator : public DecoderVisitor, public SimulatorBase { void CheckBTypeForPAuth() { DCHECK(pc_->IsPAuth()); Instr instr = pc_->Mask(SystemPAuthMask); - // Only PACI[AB]SP allowed here, but we don't currently support PACIBSP. - CHECK_EQ(instr, PACIASP); + // Only PACI[AB]SP allowed here, and we only support PACIBSP. + CHECK(instr == PACIBSP); // Check BType allows PACI[AB]SP instructions. switch (btype()) { case BranchFromGuardedNotToIP: @@ -837,7 +837,7 @@ class Simulator : public DecoderVisitor, public SimulatorBase { // here to be set. This makes PACI[AB]SP behave like "BTI c", // disallowing its execution when BTYPE is BranchFromGuardedNotToIP // (0b11). - FATAL("Executing PACIASP with wrong BType."); + FATAL("Executing PACIBSP with wrong BType."); case BranchFromUnguardedOrToIP: case BranchAndLink: break; @@ -1397,7 +1397,7 @@ class Simulator : public DecoderVisitor, public SimulatorBase { int number; }; - static const PACKey kPACKeyIA; + static const PACKey kPACKeyIB; // Current implementation is that all pointers are tagged. static bool HasTBI(uint64_t ptr, PointerType type) { @@ -2179,6 +2179,7 @@ class Simulator : public DecoderVisitor, public SimulatorBase { int64_t FPToInt64(double value, FPRounding rmode); uint32_t FPToUInt32(double value, FPRounding rmode); uint64_t FPToUInt64(double value, FPRounding rmode); + int32_t FPToFixedJS(double value); template <typename T> T FPAdd(T op1, T op2); diff --git a/chromium/v8/src/execution/arm64/simulator-logic-arm64.cc b/chromium/v8/src/execution/arm64/simulator-logic-arm64.cc index d855c8b7084..db39408a49e 100644 --- a/chromium/v8/src/execution/arm64/simulator-logic-arm64.cc +++ b/chromium/v8/src/execution/arm64/simulator-logic-arm64.cc @@ -3342,6 +3342,65 @@ LogicVRegister Simulator::frsqrts(VectorFormat vform, LogicVRegister dst, return dst; } +int32_t Simulator::FPToFixedJS(double value) { + // The Z-flag is set when the conversion from double precision floating-point + // to 32-bit integer is exact. If the source value is +/-Infinity, -0.0, NaN, + // outside the bounds of a 32-bit integer, or isn't an exact integer then the + // Z-flag is unset. + int Z = 1; + int32_t result; + if ((value == 0.0) || (value == kFP64PositiveInfinity) || + (value == kFP64NegativeInfinity)) { + // +/- zero and infinity all return zero, however -0 and +/- Infinity also + // unset the Z-flag. + result = 0.0; + if ((value != 0.0) || std::signbit(value)) { + Z = 0; + } + } else if (std::isnan(value)) { + // NaN values unset the Z-flag and set the result to 0. + result = 0; + Z = 0; + } else { + // All other values are converted to an integer representation, rounded + // toward zero. + double int_result = std::floor(value); + double error = value - int_result; + if ((error != 0.0) && (int_result < 0.0)) { + int_result++; + } + // Constrain the value into the range [INT32_MIN, INT32_MAX]. We can almost + // write a one-liner with std::round, but the behaviour on ties is incorrect + // for our purposes. + double mod_const = static_cast<double>(UINT64_C(1) << 32); + double mod_error = + (int_result / mod_const) - std::floor(int_result / mod_const); + double constrained; + if (mod_error == 0.5) { + constrained = INT32_MIN; + } else { + constrained = int_result - mod_const * round(int_result / mod_const); + } + DCHECK(std::floor(constrained) == constrained); + DCHECK(constrained >= INT32_MIN); + DCHECK(constrained <= INT32_MAX); + // Take the bottom 32 bits of the result as a 32-bit integer. + result = static_cast<int32_t>(constrained); + if ((int_result < INT32_MIN) || (int_result > INT32_MAX) || + (error != 0.0)) { + // If the integer result is out of range or the conversion isn't exact, + // take exception and unset the Z-flag. + FPProcessException(); + Z = 0; + } + } + nzcv().SetN(0); + nzcv().SetZ(Z); + nzcv().SetC(0); + nzcv().SetV(0); + return result; +} + LogicVRegister Simulator::frsqrts(VectorFormat vform, LogicVRegister dst, const LogicVRegister& src1, const LogicVRegister& src2) { |