Skip to content

Commit

Permalink
Arm64-PAC: Add encoding for pointer authentication (PAC) instructions (
Browse files Browse the repository at this point in the history
…#110160)

* Add encoding for pointer authentication (PAC) instructions

* Update latency and throughput values

* Remove todo
  • Loading branch information
SwapnilGaikwad authored Nov 26, 2024
1 parent ead4d81 commit 9f1494a
Show file tree
Hide file tree
Showing 7 changed files with 173 additions and 3 deletions.
1 change: 1 addition & 0 deletions src/coreclr/jit/codegen.h
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,7 @@ class CodeGen final : public CodeGenInterface
void genArm64EmitterUnitTestsGeneral();
void genArm64EmitterUnitTestsAdvSimd();
void genArm64EmitterUnitTestsSve();
void genArm64EmitterUnitTestsPac();
#endif

#if defined(TARGET_AMD64)
Expand Down
28 changes: 28 additions & 0 deletions src/coreclr/jit/codegenarm64test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9111,4 +9111,32 @@ void CodeGen::genArm64EmitterUnitTestsSve()
theEmitter->emitIns_R_R_I(INS_sve_extq, EA_SCALABLE, REG_V31, REG_V31, 15, INS_OPTS_SCALABLE_B);
}

/*****************************************************************************
* Unit tests for Pointer Authentication (PAC) instructions.
*/
void CodeGen::genArm64EmitterUnitTestsPac()
{
emitter* theEmitter = GetEmitter();

genDefineTempLabel(genCreateTempLabel());

// IF_PC_0A
theEmitter->emitIns(INS_autia1716); // AUTIA1716
theEmitter->emitIns(INS_autiasp); // AUTIASP
theEmitter->emitIns(INS_autiaz); // AUTIAZ
theEmitter->emitIns(INS_pacia1716); // PACIA1716
theEmitter->emitIns(INS_paciasp); // PACIASP
theEmitter->emitIns(INS_paciaz); // PACIAZ
theEmitter->emitIns(INS_xpaclri); // XPACLRI

// IF_PC_1A
theEmitter->emitIns_R(INS_autiza, EA_8BYTE, REG_R1); // AUTIZA <Xd>
theEmitter->emitIns_R(INS_paciza, EA_8BYTE, REG_R8); // PACIZA <Xd>
theEmitter->emitIns_R(INS_xpacd, EA_8BYTE, REG_R10); // XPACD <Xd>
theEmitter->emitIns_R(INS_xpaci, EA_8BYTE, REG_R12); // XPACI <Xd>

// IF_PC_2A
theEmitter->emitIns_R_R(INS_autia, EA_8BYTE, REG_R20, REG_SP); // AUTIA <Xd>, <Xn|SP>
theEmitter->emitIns_R_R(INS_pacia, EA_8BYTE, REG_R27, REG_SP); // PACIA <Xd>, <Xn|SP>
}
#endif // defined(TARGET_ARM64) && defined(DEBUG)
4 changes: 4 additions & 0 deletions src/coreclr/jit/codegenlinear.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2716,6 +2716,10 @@ void CodeGen::genEmitterUnitTests()
{
genArm64EmitterUnitTestsSve();
}
if (unitTestSectionAll || (strstr(unitTestSection, "pac") != nullptr))
{
genArm64EmitterUnitTestsPac();
}
#endif

genDefineTempLabel(skipLabel);
Expand Down
93 changes: 90 additions & 3 deletions src/coreclr/jit/emitarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -940,6 +940,18 @@ void emitter::emitInsSanityCheck(instrDesc* id)
assert(isVectorRegister(id->idReg4()));
break;

case IF_PC_1A: // PC_1A ................ ...........ddddd Rd
assert(id->idOpSize() == EA_8BYTE);
assert(isGeneralRegister(id->idReg1()));
break;

case IF_PC_2A: // PC_2A X........X...... ......nnnnnddddd Rd Rn
assert(id->idOpSize() == EA_8BYTE);
assert(isGeneralRegister(id->idReg1()));
assert(isIntegerRegister(id->idReg2())); // SP
break;

case IF_PC_0A: // PC_0A ................ ................
case IF_SN_0A: // SN_0A ................ ................
case IF_SI_0A: // SI_0A ...........iiiii iiiiiiiiiii..... imm16
case IF_SI_0B: // SI_0B ................ ....bbbb........ imm4 - barrier
Expand Down Expand Up @@ -1066,6 +1078,12 @@ bool emitter::emitInsMayWriteToGCReg(instrDesc* id)
assert(emitInsIsLoad(ins));
return true;

case IF_PC_1A: // PC_1A ................ ...........ddddd Rd
return (ins == INS_autiza || ins == INS_paciza || ins == INS_xpacd || ins == INS_xpaci);

case IF_PC_2A: // PC_2A X........X...... ......nnnnnddddd Rd Rn
return (ins == INS_autia || ins == INS_pacia);

case IF_SR_1A: // SR_1A ................ ...........ttttt Rt (dc zva, mrs)
return ins == INS_mrs_tpid0;

Expand Down Expand Up @@ -3651,7 +3669,22 @@ void emitter::emitIns(instruction ins)

if (ins != INS_BREAKPOINT)
{
assert(fmt == IF_SN_0A);
switch (ins)
{
case INS_autia1716:
case INS_autiasp:
case INS_autiaz:
case INS_pacia1716:
case INS_paciasp:
case INS_paciaz:
case INS_xpaclri:
assert(fmt == IF_PC_0A);
break;

default:
assert(fmt == IF_SN_0A);
break;
}
}

id->idIns(ins);
Expand Down Expand Up @@ -3717,9 +3750,13 @@ void emitter::emitIns_R(instruction ins, emitAttr attr, regNumber reg, insOpts o
break;

case INS_dczva:
case INS_autiza:
case INS_paciza:
case INS_xpacd:
case INS_xpaci:
assert(isGeneralRegister(reg));
assert(attr == EA_8BYTE);
fmt = IF_SR_1A;
fmt = (ins == INS_dczva) ? IF_SR_1A : IF_PC_1A;
break;

case INS_mrs_tpid0:
Expand Down Expand Up @@ -5043,6 +5080,18 @@ void emitter::emitIns_R_R(instruction ins,
}
break;

case INS_autia:
case INS_pacia:
{
assert(insOptsNone(opt));
assert(isValidGeneralDatasize(size));
assert(isGeneralRegister(reg1));
assert(isGeneralRegisterOrSP(reg2));
reg2 = encodingSPtoZR(reg2);
fmt = IF_PC_2A;
break;
}

default:
// fallback to emit SVE instructions.
return emitInsSve_R_R(ins, attr, reg1, reg2, opt, sopt);
Expand Down Expand Up @@ -5653,7 +5702,8 @@ void emitter::emitIns_R_R_I(instruction ins,
case INS_stlurb:
case INS_stlurh:
case INS_stlur:
fmt = IF_LS_2C;
reg2 = encodingSPtoZR(reg2);
fmt = IF_LS_2C;
break;

case INS_ld2:
Expand Down Expand Up @@ -11562,6 +11612,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
break;

case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
case IF_PC_2A: // PC_2A X........X...... ......nnnnnddddd Rd Rn
code = emitInsCode(ins, fmt);
code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
code |= insEncodeReg_Rd(id->idReg1()); // ddddd
Expand Down Expand Up @@ -12090,6 +12141,14 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
dst += emitOutput_Instr(dst, code);
break;

case IF_PC_1A: // PC_1A ................ ...........ddddd Rd
assert(insOptsNone(id->idInsOpt()));
code = emitInsCode(ins, fmt);
code |= insEncodeReg_Rd(id->idReg1()); // ddddd
dst += emitOutput_Instr(dst, code);
break;

case IF_PC_0A: // PC_0A ................ ................
case IF_SN_0A: // SN_0A ................ ................
{
bool skipIns = false;
Expand Down Expand Up @@ -14308,6 +14367,7 @@ void emitter::emitDispInsHelp(
emitDispReg(id->idReg4(), size, false);
break;

case IF_PC_0A: // PC_0A ................ ................
case IF_SN_0A: // SN_0A ................ ................
if (ins == INS_align)
{
Expand All @@ -14323,6 +14383,15 @@ void emitter::emitDispInsHelp(
}
break;

case IF_PC_1A: // PC_1A ................ ...........ddddd Rd
emitDispReg(id->idReg1(), size, false);
break;

case IF_PC_2A: // PC_2A X........X...... ......nnnnnddddd Rd Rn
emitDispReg(id->idReg1(), size, true);
emitDispReg(encodingZRtoSP(id->idReg2()), size, false);
break;

case IF_SI_0A: // SI_0A ...........iiiii iiiiiiiiiii..... imm16
emitDispImm(emitGetInsSC(id), false);
break;
Expand Down Expand Up @@ -15681,6 +15750,24 @@ emitter::insExecutionCharacteristics emitter::getInsExecutionCharacteristics(ins
}
break;

case IF_PC_0A: // autia1716, autiasp, autiaz, pacia1716, paciasp, paciaz, xpaclri
case IF_PC_1A: // autiza, paciza, xpacd, xpaci
case IF_PC_2A: // autia, pacia
switch (ins)
{
case INS_xpacd:
case INS_xpaci:
case INS_xpaclri:
result.insThroughput = PERFSCORE_THROUGHPUT_1C;
result.insLatency = PERFSCORE_LATENCY_2C;
break;

default:
result.insThroughput = PERFSCORE_THROUGHPUT_1C;
result.insLatency = PERFSCORE_LATENCY_5C;
}
break;

case IF_SN_0A: // nop, yield, align

if (id->idIns() == INS_align)
Expand Down
6 changes: 6 additions & 0 deletions src/coreclr/jit/emitarm64sve.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18445,6 +18445,12 @@ void emitter::emitInsPairSanityCheck(instrDesc* firstId, instrDesc* secondId)
return;
}

// Do not sanity check when unit tests are enabled.
if (JitConfig.JitEmitUnitTestsSections() != nullptr)
{
return;
}

// Currently only concerned with instructions that follow movprfx
if (firstId->idIns() != INS_sve_movprfx)
{
Expand Down
5 changes: 5 additions & 0 deletions src/coreclr/jit/emitfmtsarm64.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,11 @@ IF_DEF(SN_0A, IS_NONE, NONE) // SN_0A ................ ................
IF_DEF(SI_0A, IS_NONE, NONE) // SI_0A ...........iiiii iiiiiiiiiii..... imm16
IF_DEF(SI_0B, IS_NONE, NONE) // SI_0B ................ ....bbbb........ imm4 - barrier

// Pointer Authentication (PAC) groups
IF_DEF(PC_0A, IS_NONE, NONE) // PC_0A ................ ................ (autia1716, autiasp, autiaz, pacia1716, paciasp, paciaz, xpaclri)
IF_DEF(PC_1A, IS_NONE, NONE) // PC_1A ................ ...........ddddd Rd (autiza, paciza, xpacd, xpaci)
IF_DEF(PC_2A, IS_NONE, NONE) // PC_2A X........X...... ......nnnnnddddd Rd Rn (autia, pacia)

IF_DEF(SR_1A, IS_NONE, NONE) // SR_1A ................ ...........ttttt Rt (dc zva, mrs)

IF_DEF(INVALID, IS_NONE, NONE) //
Expand Down
39 changes: 39 additions & 0 deletions src/coreclr/jit/instrsarm64.h
Original file line number Diff line number Diff line change
Expand Up @@ -1587,6 +1587,45 @@ INST1(uxtb, "uxtb", 0, IF_DR_2H, 0x53001C00)
INST1(uxth, "uxth", 0, IF_DR_2H, 0x53003C00)
// uxth Rd,Rn DR_2H 0101001100000000 001111nnnnnddddd 5300 3C00

INST1(autia1716, "autia1716", 0, IF_PC_0A, 0xD503219F)
// autia1716 PC_0A 1101010100000011 0010000110011111 D503 219F

INST1(autiasp, "autiasp", 0, IF_PC_0A, 0xD50323BF)
// autiasp PC_0A 1101010100000011 0010001110111111 D503 23BF

INST1(autiaz, "autiaz", 0, IF_PC_0A, 0xD503239F)
// autiaz PC_0A 1101010100000011 0010001110011111 D503 239F

INST1(pacia1716, "pacia1716 ", 0, IF_PC_0A, 0xD503211F)
// pacia1716 PC_0A 1101010100000011 0010000100011111 D503 211F

INST1(paciasp, "paciasp", 0, IF_PC_0A, 0xD503233F)
// paciasp PC_0A 1101010100000011 0010001100111111 D503 233F

INST1(paciaz, "paciaz", 0, IF_PC_0A, 0xD503231F)
// paciaz PC_0A 1101010100000011 0010001100011111 D503 231F

INST1(xpaclri, "xpaclri", 0, IF_PC_0A, 0xD50320FF)
// xpaclri Rd PC_0A 1101010100000011 0010000011111111 D503 20FF

INST1(autiza, "autiza", 0, IF_PC_1A, 0xDAC133E0)
// autiza Rd PC_1A 1101101011000001 0001000000000000 DAC1 33E0

INST1(paciza, "paciza", 0, IF_PC_1A, 0xDAC123E0)
// paciza Rd PC_1A 1101101011000001 00000011111ddddd DAC1 23E0

INST1(xpacd, "xpacd", 0, IF_PC_1A, 0xDAC147E0)
// xpacd Rd PC_0A 1101101011000001 0100011111100000 DAC1 47E0

INST1(xpaci, "xpaci", 0, IF_PC_1A, 0xDAC143E0)
// xpaci Rd PC_0A 1101101011000001 0100001111100000 DAC1 43E0

INST1(autia, "autia", 0, IF_PC_2A, 0xDAC11000)
// autia Rd,Rn PC_2A 1101101011000001 00110011111ddddd DAC1 1000

INST1(pacia, "pacia", 0, IF_PC_2A, 0xDAC10000)
// pacia Rd,Rn PC_2A 1101101011000001 000000nnnnnddddd DAC1 0000

INST1(nop, "nop", 0, IF_SN_0A, 0xD503201F)
// nop SN_0A 1101010100000011 0010000000011111 D503 201F

Expand Down

0 comments on commit 9f1494a

Please sign in to comment.