POWER10: Add Return-Oriented Programming instructions
authorPeter Bergner <bergner@linux.ibm.com>
Fri, 8 Jan 2021 22:07:12 +0000 (16:07 -0600)
committerAlan Modra <amodra@gmail.com>
Sat, 9 Jan 2021 04:46:13 +0000 (15:16 +1030)
POWER10 adds some return-oriented programming (ROP) instructions and
this patch adds support for them.  You will notice that they are enabled
for POWER8 and later, not just POWER10 and later.  This is on purpose.
This allows the instructions to be added to POWER8 binaries that can be
run on POWER8, POWER9 and POWER10 cpus.  On POWER8 and POWER9, these
instructions just act as nop's.

opcodes/
* ppc-opc.c (insert_dw, (extract_dw): New functions.
(DW, (XRC_MASK): Define.
(powerpc_opcodes) <hashchk, hashchkp, hashst, haststp>: New mnemonics.
gas/
* testsuite/gas/ppc/rop-checks.d,
* testsuite/gas/ppc/rop-checks.l,
* testsuite/gas/ppc/rop-checks.s,
* testsuite/gas/ppc/rop.d,
* testsuite/gas/ppc/rop.s: New tests.
* testsuite/gas/ppc/ppc.exp: Run them.

gas/ChangeLog
gas/testsuite/gas/ppc/ppc.exp
gas/testsuite/gas/ppc/rop-checks.d [new file with mode: 0644]
gas/testsuite/gas/ppc/rop-checks.l [new file with mode: 0644]
gas/testsuite/gas/ppc/rop-checks.s [new file with mode: 0644]
gas/testsuite/gas/ppc/rop.d [new file with mode: 0644]
gas/testsuite/gas/ppc/rop.s [new file with mode: 0644]
opcodes/ChangeLog
opcodes/ppc-opc.c

index a2cdedaee93a2b6d3feb2a73bc145838e948f1fa..cb38110d417b52b862c2b35e72ca909764e556db 100644 (file)
@@ -1,3 +1,12 @@
+2021-01-08  Peter Bergner  <bergner@linux.ibm.com>
+
+       * testsuite/gas/ppc/rop-checks.d,
+       * testsuite/gas/ppc/rop-checks.l,
+       * testsuite/gas/ppc/rop-checks.s,
+       * testsuite/gas/ppc/rop.d,
+       * testsuite/gas/ppc/rop.s: New tests.
+       * testsuite/gas/ppc/ppc.exp: Run them.
+
 2021-01-09  Alan Modra  <amodra@gmail.com>
 
        * configure: Regenerate.
index bec31513357dc8f83a100953aa635e032f7bc715..6f61ad09f41f19f53fb3ab7fdf61f2c0cebf213a 100644 (file)
@@ -146,5 +146,7 @@ run_dump_test "stringop"
 run_dump_test "xvtlsbb"
 run_dump_test "rightmost"
 run_dump_test "scalarquad"
+run_dump_test "rop"
+run_dump_test "rop-checks"
 
 run_dump_test "dcbt"
diff --git a/gas/testsuite/gas/ppc/rop-checks.d b/gas/testsuite/gas/ppc/rop-checks.d
new file mode 100644 (file)
index 0000000..b7ef25e
--- /dev/null
@@ -0,0 +1,3 @@
+#as: -mpower10
+#name: Test Return-Oriented Programming checks
+#error_output: rop-checks.l
diff --git a/gas/testsuite/gas/ppc/rop-checks.l b/gas/testsuite/gas/ppc/rop-checks.l
new file mode 100644 (file)
index 0000000..83ffbee
--- /dev/null
@@ -0,0 +1,17 @@
+[^:]*: Assembler messages:
+[^:]*:3: Error: invalid offset: must be in the range \[-512, -8\] and be a multiple of 8
+[^:]*:4: Error: invalid offset: must be in the range \[-512, -8\] and be a multiple of 8
+[^:]*:5: Error: invalid offset: must be in the range \[-512, -8\] and be a multiple of 8
+[^:]*:6: Error: invalid offset: must be in the range \[-512, -8\] and be a multiple of 8
+[^:]*:7: Error: invalid offset: must be in the range \[-512, -8\] and be a multiple of 8
+[^:]*:8: Error: invalid offset: must be in the range \[-512, -8\] and be a multiple of 8
+[^:]*:9: Error: invalid offset: must be in the range \[-512, -8\] and be a multiple of 8
+[^:]*:10: Error: invalid offset: must be in the range \[-512, -8\] and be a multiple of 8
+[^:]*:11: Error: invalid offset: must be in the range \[-512, -8\] and be a multiple of 8
+[^:]*:12: Error: invalid offset: must be in the range \[-512, -8\] and be a multiple of 8
+[^:]*:13: Error: invalid offset: must be in the range \[-512, -8\] and be a multiple of 8
+[^:]*:14: Error: invalid offset: must be in the range \[-512, -8\] and be a multiple of 8
+[^:]*:15: Error: invalid offset: must be in the range \[-512, -8\] and be a multiple of 8
+[^:]*:16: Error: invalid offset: must be in the range \[-512, -8\] and be a multiple of 8
+[^:]*:17: Error: invalid offset: must be in the range \[-512, -8\] and be a multiple of 8
+[^:]*:18: Error: invalid offset: must be in the range \[-512, -8\] and be a multiple of 8
diff --git a/gas/testsuite/gas/ppc/rop-checks.s b/gas/testsuite/gas/ppc/rop-checks.s
new file mode 100644 (file)
index 0000000..83ca35a
--- /dev/null
@@ -0,0 +1,18 @@
+       .text
+_start:
+       hashst   20,8(1)
+       hashst   21,0(1)
+       hashst   22,-12(1)
+       hashst   23,-520(1)
+       hashchk  20,8(1)
+       hashchk  21,0(1)
+       hashchk  22,-12(1)
+       hashchk  23,-520(1)
+       hashstp  20,8(1)
+       hashstp  21,0(1)
+       hashstp  22,-12(1)
+       hashstp  23,-520(1)
+       hashchkp 20,8(1)
+       hashchkp 21,0(1)
+       hashchkp 22,-12(1)
+       hashchkp 23,-520(1)
diff --git a/gas/testsuite/gas/ppc/rop.d b/gas/testsuite/gas/ppc/rop.d
new file mode 100644 (file)
index 0000000..2671dd6
--- /dev/null
@@ -0,0 +1,27 @@
+#as: -mpower8
+#objdump: -d -Mpower8
+#name: Return-Oriented Programming tests
+
+.*
+
+
+Disassembly of section \.text:
+
+0+0 <_start>:
+.*:    (7f e1 a5 a5|a5 a5 e1 7f)       hashst  r20,-8\(r1\)
+.*:    (7f c1 ad a5|a5 ad c1 7f)       hashst  r21,-16\(r1\)
+.*:    (7c 01 b5 a5|a5 b5 01 7c)       hashst  r22,-256\(r1\)
+.*:    (7c 01 bd a4|a4 bd 01 7c)       hashst  r23,-512\(r1\)
+.*:    (7f e1 a5 e5|e5 a5 e1 7f)       hashchk r20,-8\(r1\)
+.*:    (7f c1 ad e5|e5 ad c1 7f)       hashchk r21,-16\(r1\)
+.*:    (7c 01 b5 e5|e5 b5 01 7c)       hashchk r22,-256\(r1\)
+.*:    (7c 01 bd e4|e4 bd 01 7c)       hashchk r23,-512\(r1\)
+.*:    (7f e1 a5 25|25 a5 e1 7f)       hashstp r20,-8\(r1\)
+.*:    (7f c1 ad 25|25 ad c1 7f)       hashstp r21,-16\(r1\)
+.*:    (7c 01 b5 25|25 b5 01 7c)       hashstp r22,-256\(r1\)
+.*:    (7c 01 bd 24|24 bd 01 7c)       hashstp r23,-512\(r1\)
+.*:    (7f e1 a5 65|65 a5 e1 7f)       hashchkp r20,-8\(r1\)
+.*:    (7f c1 ad 65|65 ad c1 7f)       hashchkp r21,-16\(r1\)
+.*:    (7c 01 b5 65|65 b5 01 7c)       hashchkp r22,-256\(r1\)
+.*:    (7c 01 bd 64|64 bd 01 7c)       hashchkp r23,-512\(r1\)
+#pass
diff --git a/gas/testsuite/gas/ppc/rop.s b/gas/testsuite/gas/ppc/rop.s
new file mode 100644 (file)
index 0000000..22e45f4
--- /dev/null
@@ -0,0 +1,21 @@
+# These instructions are new in POWER10, but enabled for POWER8 and
+# later cpus.  On POWER8 and POWER9, these instructions behave as
+# nop's.
+       .text
+_start:
+       hashst   20,-8(1)
+       hashst   21,-16(1)
+       hashst   22,-256(1)
+       hashst   23,-512(1)
+       hashchk  20,-8(1)
+       hashchk  21,-16(1)
+       hashchk  22,-256(1)
+       hashchk  23,-512(1)
+       hashstp  20,-8(1)
+       hashstp  21,-16(1)
+       hashstp  22,-256(1)
+       hashstp  23,-512(1)
+       hashchkp 20,-8(1)
+       hashchkp 21,-16(1)
+       hashchkp 22,-256(1)
+       hashchkp 23,-512(1)
index 205c0ad6c37031a300d3c051effab28c8e765b9a..6b48181d887f71e45586487d519947934b301e20 100644 (file)
@@ -1,3 +1,9 @@
+2021-01-08  Peter Bergner  <bergner@linux.ibm.com>
+
+       * ppc-opc.c (insert_dw, (extract_dw): New functions.
+       (DW, (XRC_MASK): Define.
+       (powerpc_opcodes) <hashchk, hashchkp, hashst, haststp>: New mnemonics.
+
 2021-01-09  Alan Modra  <amodra@gmail.com>
 
        * configure: Regenerate.
index dcff56205d44d253d8a4b141ba8c0a81522612dc..bbbadffad8f62f867c53630b9bf67cfe72ecfed6 100644 (file)
@@ -558,6 +558,34 @@ extract_dcmxs (uint64_t insn,
   return (insn & 0x40) | ((insn << 3) & 0x20) | ((insn >> 16) & 0x1f);
 }
 
+/* The DW field in a X form instruction when the field is split
+   into separate D and DX fields.  */
+
+static uint64_t
+insert_dw (uint64_t insn,
+          int64_t value,
+          ppc_cpu_t dialect ATTRIBUTE_UNUSED,
+          const char **errmsg ATTRIBUTE_UNUSED)
+{
+  /* DW offsets must be in the range [-512, -8] and be a multiple of 8.  */
+  if (value < -512
+      || value > -8
+      || (value & 0x7) != 0)
+    *errmsg = _("invalid offset: must be in the range [-512, -8] "
+               "and be a multiple of 8");
+
+  return insn | ((value & 0xf8) << 18) | ((value >> 8) & 1);
+}
+
+static int64_t
+extract_dw (uint64_t insn,
+            ppc_cpu_t dialect ATTRIBUTE_UNUSED,
+            int *invalid ATTRIBUTE_UNUSED)
+{
+  int64_t dw = ((insn & 1) << 8) | ((insn >> 18) & 0xf8);
+  return dw - 512;
+}
+
 /* The D field in a DX form instruction when the field is split
    into separate D0, D1 and D2 fields.  */
 
@@ -2497,8 +2525,13 @@ const struct powerpc_operand powerpc_operands[] =
 #define BHRBE DUIS
   { 0x3ff, 11, NULL, NULL, 0 },
 
+  /* The split DW field in a X form instruction.  */
+#define DW DUIS + 1
+  { -1, PPC_OPSHIFT_INV, insert_dw, extract_dw,
+    PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED},
+
   /* The split D field in a DX form instruction.  */
-#define DXD DUIS + 1
+#define DXD DW + 1
   { 0xffff, PPC_OPSHIFT_INV, insert_dxd, extract_dxd,
     PPC_OPERAND_SIGNED | PPC_OPERAND_SIGNOPT},
 
@@ -3750,6 +3783,9 @@ const unsigned int num_powerpc_operands = (sizeof (powerpc_operands)
 /* The mask for an X form instruction with the BF bits specified.  */
 #define XBF_MASK (X_MASK | (3 << 21))
 
+/* An X form instruction without the RC field specified.  */
+#define XRC_MASK XRC (0x3f, 0x3ff, 0)
+
 /* An X form wait instruction with everything filled in except the WC
    field.  */
 #define XWC_MASK (XRC (0x3f, 0x3ff, 1) | (7 << 23) | RA_MASK | RB_MASK)
@@ -7656,6 +7692,8 @@ const struct powerpc_opcode powerpc_opcodes[] = {
 {"addeo.",     XO(31,138,1,1), XO_MASK,     PPCCOM,    0,              {RT, RA, RB}},
 {"aeo.",       XO(31,138,1,1), XO_MASK,     PWRCOM,    0,              {RT, RA, RB}},
 
+{"hashstp",    X(31,658),      XRC_MASK,    POWER8,    0,              {RB, DW, RA0}},
+
 {"mfsrin",     X(31,659),      XRA_MASK,    PPC,       NON32,          {RT, RB}},
 
 {"stdbrx",     X(31,660),      X_MASK, CELL|POWER7|PPCA2, 0,           {RS, RA0, RB}},
@@ -7685,6 +7723,8 @@ const struct powerpc_opcode powerpc_opcodes[] = {
 {"tendall.",   XRC(31,686,1)|(1<<25), XRTRARB_MASK, PPCHTM, 0,         {0}},
 {"tend.",      XRC(31,686,1), XRTARARB_MASK, PPCHTM,   0,              {HTM_A}},
 
+{"hashchkp",   X(31,690),      XRC_MASK,    POWER8,    0,              {RB, DW, RA0}},
+
 {"stbcx.",     XRC(31,694,1),  X_MASK,   POWER8|E6500, 0,              {RS, RA0, RB}},
 
 {"stfsux",     X(31,695),      X_MASK,      COM,       PPCEFS,         {FRS, RAS, RB}},
@@ -7715,6 +7755,8 @@ const struct powerpc_opcode powerpc_opcodes[] = {
 {"addzeo.",    XO(31,202,1,1), XORB_MASK,   PPCCOM,    0,              {RT, RA}},
 {"azeo.",      XO(31,202,1,1), XORB_MASK,   PWRCOM,    0,              {RT, RA}},
 
+{"hashst",     X(31,722),      XRC_MASK,    POWER8,    0,              {RB, DW, RA0}},
+
 {"stswi",      X(31,725),      X_MASK,      PPCCOM,    E500|E500MC,    {RS, RA0, NB}},
 {"stsi",       X(31,725),      X_MASK,      PWRCOM,    0,              {RS, RA0, NB}},
 
@@ -7761,6 +7803,8 @@ const struct powerpc_opcode powerpc_opcodes[] = {
 {"tresume.",   XRCL(31,750,1,1), XRTRARB_MASK,PPCHTM,  0,              {0}},
 {"tsr.",       XRC(31,750,1),    XRTLRARB_MASK,PPCHTM, 0,              {L}},
 
+{"hashchk",    X(31,754),      XRC_MASK,    POWER8,    0,              {RB, DW, RA0}},
+
 {"darn",       X(31,755),      XLRAND_MASK, POWER9,    0,              {RT, LRAND}},
 
 {"dcba",       X(31,758), XRT_MASK, PPC405|PPC7450|BOOKE|PPCA2|PPC476, 0, {RA0, RB}},