[llvm] 16fe741 - [PowerPC] Add ROP Protection Instructions for PowerPC

Stefan Pintilie via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 9 10:09:08 PDT 2021


Author: Stefan Pintilie
Date: 2021-04-09T12:09:01-05:00
New Revision: 16fe741c69429235210c03c46420f8fa6aece4a1

URL: https://github.com/llvm/llvm-project/commit/16fe741c69429235210c03c46420f8fa6aece4a1
DIFF: https://github.com/llvm/llvm-project/commit/16fe741c69429235210c03c46420f8fa6aece4a1.diff

LOG: [PowerPC] Add ROP Protection Instructions for PowerPC

There are four new PowerPC instructions that are introduced in
Power 10. They are hashst, hashchk, hashstp, hashchkp.

These instructions will be used for ROP Protection.
This patch adds the four instructions.

Reviewed By: nemanjai, amyk, #powerpc

Differential Revision: https://reviews.llvm.org/D99375

Added: 
    

Modified: 
    llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
    llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp
    llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp
    llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.h
    llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp
    llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h
    llvm/lib/Target/PowerPC/P9InstrResources.td
    llvm/lib/Target/PowerPC/PPCInstr64Bit.td
    llvm/lib/Target/PowerPC/PPCInstrFormats.td
    llvm/lib/Target/PowerPC/PPCInstrInfo.td
    llvm/test/MC/Disassembler/PowerPC/ppc64-encoding-ISA31.txt
    llvm/test/MC/PowerPC/ppc64-encoding-ISA31.s

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
index ba40e23c782cf..54e73137ebd27 100644
--- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
+++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
@@ -359,6 +359,15 @@ struct PPCOperand : public MCParsedAsmOperand {
   bool isS16ImmX4() const { return Kind == Expression ||
                                    (Kind == Immediate && isInt<16>(getImm()) &&
                                     (getImm() & 3) == 0); }
+
+  bool isHashImmX8() const {
+    // The Hash Imm form is used for instructions that check or store a hash.
+    // These instructions have a small immediate range that spans between
+    // -8 and -512.
+    return (Kind == Immediate && getImm() <= -8 && getImm() >= -512 &&
+            (getImm() & 7) == 0);
+  }
+
   bool isS16ImmX16() const { return Kind == Expression ||
                                     (Kind == Immediate && isInt<16>(getImm()) &&
                                      (getImm() & 15) == 0); }

diff  --git a/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp b/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp
index 3e9286fb0b30b..706f6df482729 100644
--- a/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp
+++ b/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp
@@ -279,6 +279,23 @@ static DecodeStatus decodeMemRIXOperands(MCInst &Inst, uint64_t Imm,
   return MCDisassembler::Success;
 }
 
+static DecodeStatus decodeMemRIHashOperands(MCInst &Inst, uint64_t Imm,
+                                            int64_t Address,
+                                            const void *Decoder) {
+  // Decode the memrix field for a hash store or hash check operation.
+  // The field is composed of a register and an immediate value that is 6 bits
+  // and covers the range -8 to -512. The immediate is always negative and 2s
+  // complement which is why we sign extend a 7 bit value.
+  const uint64_t Base = Imm >> 6;
+  const uint64_t Disp = SignExtend64<7>((Imm & 0x3F) + 64) << 3;
+
+  assert(Base < 32 && "Invalid base register");
+
+  Inst.addOperand(MCOperand::createImm(Disp));
+  Inst.addOperand(MCOperand::createReg(RRegs[Base]));
+  return MCDisassembler::Success;
+}
+
 static DecodeStatus decodeMemRIX16Operands(MCInst &Inst, uint64_t Imm,
                                          int64_t Address, const void *Decoder) {
   // Decode the memrix16 field (imm, reg), which has the low 12-bits as the

diff  --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp
index a291a34d4c52d..3f6497aa0e8f4 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp
@@ -514,6 +514,15 @@ void PPCInstPrinter::printMemRegImm(const MCInst *MI, unsigned OpNo,
   O << ')';
 }
 
+void PPCInstPrinter::printMemRegImmHash(const MCInst *MI, unsigned OpNo,
+                                        const MCSubtargetInfo &STI,
+                                        raw_ostream &O) {
+  O << MI->getOperand(OpNo).getImm();
+  O << '(';
+  printOperand(MI, OpNo + 1, STI, O);
+  O << ')';
+}
+
 void PPCInstPrinter::printMemRegImm34PCRel(const MCInst *MI, unsigned OpNo,
                                            const MCSubtargetInfo &STI,
                                            raw_ostream &O) {

diff  --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.h b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.h
index 5e9b01494416a..8f676da9b466e 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.h
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.h
@@ -97,6 +97,8 @@ class PPCInstPrinter : public MCInstPrinter {
 
   void printMemRegImm(const MCInst *MI, unsigned OpNo,
                       const MCSubtargetInfo &STI, raw_ostream &O);
+  void printMemRegImmHash(const MCInst *MI, unsigned OpNo,
+                          const MCSubtargetInfo &STI, raw_ostream &O);
   void printMemRegImm34PCRel(const MCInst *MI, unsigned OpNo,
                              const MCSubtargetInfo &STI, raw_ostream &O);
   void printMemRegImm34(const MCInst *MI, unsigned OpNo,

diff  --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp
index 5f0769fd21f9d..4dfa7d5e600c1 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp
@@ -203,6 +203,24 @@ unsigned PPCMCCodeEmitter::getMemRIX16Encoding(const MCInst &MI, unsigned OpNo,
   return RegBits;
 }
 
+unsigned
+PPCMCCodeEmitter::getMemRIHashEncoding(const MCInst &MI, unsigned OpNo,
+                                       SmallVectorImpl<MCFixup> &Fixups,
+                                       const MCSubtargetInfo &STI) const {
+  // Encode (imm, reg) for the hash load/store to stack for the ROP Protection
+  // instructions.
+  const MCOperand &RegMO = MI.getOperand(OpNo + 1);
+  const MCOperand &MO = MI.getOperand(OpNo);
+
+  assert(RegMO.isReg() && "Base address must be a register.");
+  assert(MO.isImm() && "Expecting an immediate operand.");
+  assert(!(MO.getImm() % 8) && "Expecting offset to be 8 byte aligned.");
+
+  unsigned RegBits = getMachineOpValue(MI, RegMO, Fixups, STI) << 6;
+  unsigned DX = (MO.getImm() >> 3) & 0x3F;
+  return RegBits | DX;
+}
+
 uint64_t
 PPCMCCodeEmitter::getMemRI34PCRelEncoding(const MCInst &MI, unsigned OpNo,
                                           SmallVectorImpl<MCFixup> &Fixups,

diff  --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h
index 347e163c9515e..39b2f1211f293 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.h
@@ -69,6 +69,9 @@ class PPCMCCodeEmitter : public MCCodeEmitter {
   unsigned getMemRIX16Encoding(const MCInst &MI, unsigned OpNo,
                                SmallVectorImpl<MCFixup> &Fixups,
                                const MCSubtargetInfo &STI) const;
+  unsigned getMemRIHashEncoding(const MCInst &MI, unsigned OpNo,
+                                SmallVectorImpl<MCFixup> &Fixups,
+                                const MCSubtargetInfo &STI) const;
   uint64_t getMemRI34PCRelEncoding(const MCInst &MI, unsigned OpNo,
                                    SmallVectorImpl<MCFixup> &Fixups,
                                    const MCSubtargetInfo &STI) const;

diff  --git a/llvm/lib/Target/PowerPC/P9InstrResources.td b/llvm/lib/Target/PowerPC/P9InstrResources.td
index 05fbe386dfa84..76f52c7d88f45 100644
--- a/llvm/lib/Target/PowerPC/P9InstrResources.td
+++ b/llvm/lib/Target/PowerPC/P9InstrResources.td
@@ -1409,6 +1409,7 @@ def : InstRW<[],
   (instregex "NOP_GT_PWR(6|7)$"),
   (instregex "TLB(IA|IVAX|SX|SX2|SX2D|LD|LI|RE|RE2|WE|WE2)$"),
   (instregex "WRTEE(I)?$"),
+  (instregex "HASH(ST|STP|CHK|CHKP)$"),
   ATTN,
   CLRBHRB,
   MFBHRBE,

diff  --git a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
index 4fcc48e4bae68..386d14381427e 100644
--- a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
+++ b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
@@ -1521,6 +1521,29 @@ defm FCTIWUZ : XForm_26r<63, 143, (outs f8rc:$frD), (ins f8rc:$frB),
                         [(set f64:$frD, (PPCany_fctiwuz f64:$frB))]>, isPPC64;
 }
 
+// These instructions store a hash computed from the value of the link register
+// and the value of the stack pointer.
+let mayStore = 1 in {
+def HASHST : XForm_XD6_RA5_RB5<31, 722, (outs),
+                               (ins g8rc:$RB, memrihash:$D_RA_XD),
+                               "hashst $RB, $D_RA_XD", IIC_IntGeneral, []>;
+def HASHSTP : XForm_XD6_RA5_RB5<31, 658, (outs),
+                                (ins g8rc:$RB, memrihash:$D_RA_XD),
+                                "hashstp $RB, $D_RA_XD", IIC_IntGeneral, []>;
+}
+
+// These instructions check a hash computed from the value of the link register
+// and the value of the stack pointer. The hasSideEffects flag is needed as the
+// instruction may TRAP if the hash does not match the hash stored at the
+// specified address.
+let mayLoad = 1, hasSideEffects = 1 in {
+def HASHCHK : XForm_XD6_RA5_RB5<31, 754, (outs),
+                                (ins g8rc:$RB, memrihash:$D_RA_XD),
+                                "hashchk $RB, $D_RA_XD", IIC_IntGeneral, []>;
+def HASHCHKP : XForm_XD6_RA5_RB5<31, 690, (outs),
+                                 (ins g8rc:$RB, memrihash:$D_RA_XD),
+                                 "hashchkp $RB, $D_RA_XD", IIC_IntGeneral, []>;
+}
 
 //===----------------------------------------------------------------------===//
 // Instruction Patterns

diff  --git a/llvm/lib/Target/PowerPC/PPCInstrFormats.td b/llvm/lib/Target/PowerPC/PPCInstrFormats.td
index 646efe64a22c7..bb25e42c4648b 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrFormats.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrFormats.td
@@ -1195,6 +1195,21 @@ class XX2_RD6_DCMX7_RS6<bits<6> opcode, bits<4> xo1, bits<3> xo2,
   let Inst{31}    = XT{5};
 }
 
+class XForm_XD6_RA5_RB5<bits<6> opcode, bits<10> xo, dag OOL, dag IOL,
+                        string asmstr, InstrItinClass itin, list<dag> pattern>
+  : I<opcode, OOL, IOL, asmstr, itin> {
+  bits<11> D_RA_XD;
+  bits<5> RB;
+
+  let Pattern = pattern;
+
+  let Inst{6-10}  = D_RA_XD{4-0};  // D
+  let Inst{11-15} = D_RA_XD{10-6}; // RA
+  let Inst{16-20} = RB;
+  let Inst{21-30} = xo;
+  let Inst{31}    = D_RA_XD{5};    // DX
+}
+
 class XX3Form<bits<6> opcode, bits<8> xo, dag OOL, dag IOL, string asmstr, 
               InstrItinClass itin, list<dag> pattern>
   : I<opcode, OOL, IOL, asmstr, itin> {

diff  --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td
index aa820eee4dcca..61c22f8db5470 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td
@@ -991,6 +991,13 @@ def PPCDispRIXOperand : AsmOperandClass {
 def dispRIX : Operand<iPTR> {
   let ParserMatchClass = PPCDispRIXOperand;
 }
+def PPCDispRIHashOperand : AsmOperandClass {
+  let Name = "DispRIHash"; let PredicateMethod = "isHashImmX8";
+  let RenderMethod = "addImmOperands";
+}
+def dispRIHash : Operand<iPTR> {
+  let ParserMatchClass = PPCDispRIHashOperand;
+}
 def PPCDispRIX16Operand : AsmOperandClass {
  let Name = "DispRIX16"; let PredicateMethod = "isS16ImmX16";
  let RenderMethod = "addImmOperands";
@@ -1039,6 +1046,14 @@ def memrix : Operand<iPTR> {   // memri where the imm is 4-aligned.
   let DecoderMethod = "decodeMemRIXOperands";
   let OperandType = "OPERAND_MEMORY";
 }
+def memrihash : Operand<iPTR> {
+  // memrihash 8-aligned for ROP Protection Instructions.
+  let PrintMethod = "printMemRegImmHash";
+  let MIOperandInfo = (ops dispRIHash:$imm, ptr_rc_nor0:$reg);
+  let EncoderMethod = "getMemRIHashEncoding";
+  let DecoderMethod = "decodeMemRIHashOperands";
+  let OperandType = "OPERAND_MEMORY";
+}
 def memrix16 : Operand<iPTR> { // memri, imm is 16-aligned, 12-bit, Inst{16:27}
   let PrintMethod = "printMemRegImm";
   let MIOperandInfo = (ops dispRIX16:$imm, ptr_rc_nor0:$reg);

diff  --git a/llvm/test/MC/Disassembler/PowerPC/ppc64-encoding-ISA31.txt b/llvm/test/MC/Disassembler/PowerPC/ppc64-encoding-ISA31.txt
index edbeeaf8826d8..7b4f2cb8b6566 100644
--- a/llvm/test/MC/Disassembler/PowerPC/ppc64-encoding-ISA31.txt
+++ b/llvm/test/MC/Disassembler/PowerPC/ppc64-encoding-ISA31.txt
@@ -767,3 +767,40 @@
 
 # CHECK: xvcvbf16spn 33, 34
 0xf0 0x30 0x17 0x6f
+
+# CHECK: hashst 5, -8(1)
+0x7f 0xe1 0x2d 0xa5
+
+# CHECK: hashst 0, -8(30)
+0x7f 0xfe 0x05 0xa5
+
+# CHECK: hashst 5, -512(1)
+0x7c 0x01 0x2d 0xa4
+
+# CHECK: hashchk 5, -8(1)
+0x7f 0xe1 0x2d 0xe5
+
+# CHECK: hashchk 0, -8(30)
+0x7f 0xfe 0x05 0xe5
+
+# CHECK: hashchk 5, -512(1)
+0x7c 0x01 0x2d 0xe4
+
+# CHECK: hashstp 5, -8(1)
+0x7f 0xe1 0x2d 0x25
+
+# CHECK: hashstp 0, -8(30)
+0x7f 0xfe 0x05 0x25
+
+# CHECK: hashstp 5, -512(1)
+0x7c 0x01 0x2d 0x24
+
+# CHECK: hashchkp 5, -8(1)
+0x7f 0xe1 0x2d 0x65
+
+# CHECK: hashchkp 0, -8(30)
+0x7f 0xfe 0x05 0x65
+
+# CHECK: hashchkp 5, -512(1)
+0x7c 0x01 0x2d 0x64
+

diff  --git a/llvm/test/MC/PowerPC/ppc64-encoding-ISA31.s b/llvm/test/MC/PowerPC/ppc64-encoding-ISA31.s
index 7ff7e02edafd7..f237a68925848 100644
--- a/llvm/test/MC/PowerPC/ppc64-encoding-ISA31.s
+++ b/llvm/test/MC/PowerPC/ppc64-encoding-ISA31.s
@@ -963,3 +963,39 @@
 # CHECK-BE: xvcvbf16spn 33, 34                    # encoding: [0xf0,0x30,0x17,0x6f]
 # CHECK-LE: xvcvbf16spn 33, 34                    # encoding: [0x6f,0x17,0x30,0xf0]
             xvcvbf16spn 33, 34
+# CHECK-BE: hashst 5, -8(1)                       # encoding: [0x7f,0xe1,0x2d,0xa5]
+# CHECK-LE: hashst 5, -8(1)                       # encoding: [0xa5,0x2d,0xe1,0x7f]
+            hashst 5, -8(1)
+# CHECK-BE: hashst 0, -8(30)                      # encoding: [0x7f,0xfe,0x05,0xa5]
+# CHECK-LE: hashst 0, -8(30)                      # encoding: [0xa5,0x05,0xfe,0x7f]
+            hashst 0, -8(30)
+# CHECK-BE: hashst 5, -512(1)                     # encoding: [0x7c,0x01,0x2d,0xa4]
+# CHECK-LE: hashst 5, -512(1)                     # encoding: [0xa4,0x2d,0x01,0x7c]
+            hashst 5, -512(1)
+# CHECK-BE: hashchk 5, -8(1)                      # encoding: [0x7f,0xe1,0x2d,0xe5]
+# CHECK-LE: hashchk 5, -8(1)                      # encoding: [0xe5,0x2d,0xe1,0x7f]
+            hashchk 5, -8(1)
+# CHECK-BE: hashchk 0, -8(30)                     # encoding: [0x7f,0xfe,0x05,0xe5]
+# CHECK-LE: hashchk 0, -8(30)                     # encoding: [0xe5,0x05,0xfe,0x7f]
+            hashchk 0, -8(30)
+# CHECK-BE: hashchk 5, -512(1)                    # encoding: [0x7c,0x01,0x2d,0xe4]
+# CHECK-LE: hashchk 5, -512(1)                    # encoding: [0xe4,0x2d,0x01,0x7c]
+            hashchk 5, -512(1)
+# CHECK-BE: hashstp 5, -8(1)                      # encoding: [0x7f,0xe1,0x2d,0x25]
+# CHECK-LE: hashstp 5, -8(1)                      # encoding: [0x25,0x2d,0xe1,0x7f]
+            hashstp 5, -8(1)
+# CHECK-BE: hashstp 0, -8(30)                     # encoding: [0x7f,0xfe,0x05,0x25]
+# CHECK-LE: hashstp 0, -8(30)                     # encoding: [0x25,0x05,0xfe,0x7f]
+            hashstp 0, -8(30)
+# CHECK-BE: hashstp 5, -512(1)                    # encoding: [0x7c,0x01,0x2d,0x24]
+# CHECK-LE: hashstp 5, -512(1)                    # encoding: [0x24,0x2d,0x01,0x7c]
+            hashstp 5, -512(1)
+# CHECK-BE: hashchkp 5, -8(1)                     # encoding: [0x7f,0xe1,0x2d,0x65]
+# CHECK-LE: hashchkp 5, -8(1)                     # encoding: [0x65,0x2d,0xe1,0x7f]
+            hashchkp 5, -8(1)
+# CHECK-BE: hashchkp 0, -8(30)                    # encoding: [0x7f,0xfe,0x05,0x65]
+# CHECK-LE: hashchkp 0, -8(30)                    # encoding: [0x65,0x05,0xfe,0x7f]
+            hashchkp 0, -8(30)
+# CHECK-BE: hashchkp 5, -512(1)                   # encoding: [0x7c,0x01,0x2d,0x64]
+# CHECK-LE: hashchkp 5, -512(1)                   # encoding: [0x64,0x2d,0x01,0x7c]
+            hashchkp 5, -512(1)


        


More information about the llvm-commits mailing list