freedreno/afuc: Handle setsecure opcode
authorConnor Abbott <cwabbott0@gmail.com>
Mon, 17 Aug 2020 12:26:49 +0000 (14:26 +0200)
committerMarge Bot <eric+marge@anholt.net>
Tue, 18 Aug 2020 16:17:31 +0000 (16:17 +0000)
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6368>

src/freedreno/afuc/afuc.h
src/freedreno/afuc/asm.c
src/freedreno/afuc/disasm.c
src/freedreno/afuc/lexer.l
src/freedreno/afuc/parser.y

index 4f9e9d2181591110a71164fd8bca2bf62f713751..a69690a56f29b39526ce7f77173090d078d8a78a 100644 (file)
@@ -109,6 +109,7 @@ typedef enum {
        OPC_CALL   = 0x35,  /* "function" call */
        OPC_WIN    = 0x36,  /* wait for input (ie. wait for WPTR to advance) */
        OPC_PREEMPTLEAVE6 = 0x38,  /* try to leave preemption */
        OPC_CALL   = 0x35,  /* "function" call */
        OPC_WIN    = 0x36,  /* wait for input (ie. wait for WPTR to advance) */
        OPC_PREEMPTLEAVE6 = 0x38,  /* try to leave preemption */
+       OPC_SETSECURE = 0x3b, /* switch secure mode on/off */
 } afuc_opc;
 
 
 } afuc_opc;
 
 
index 56036be46f68794d0cc25aeb8197c61c233a8844..896a8555cf3d49f875cc7354cff1297acf8e1479 100644 (file)
@@ -262,6 +262,17 @@ static void emit_instructions(int outfd)
                        opc = OPC_PREEMPTLEAVE6;
                        instr.call.uoff = resolve_label(ai->label);
                        break;
                        opc = OPC_PREEMPTLEAVE6;
                        instr.call.uoff = resolve_label(ai->label);
                        break;
+               case T_OP_SETSECURE:
+                       opc = OPC_SETSECURE;
+                       if (resolve_label(ai->label) != i + 3) {
+                               fprintf(stderr, "jump label %s is incorrect for setsecure\n", ai->label);
+                               exit(1);
+                       }
+                       if (ai->src1 != 0x2) {
+                               fprintf(stderr, "source for setsecure must be $02\n");
+                               exit(1);
+                       }
+                       break;
                case T_OP_JUMP:
                        /* encode jump as: brne $00, b0, #label */
                        opc = OPC_BRNEB;
                case T_OP_JUMP:
                        /* encode jump as: brne $00, b0, #label */
                        opc = OPC_BRNEB;
index d170b152fad08deb531f699d8c5472901e241f0c..5c86f4327dabd8c4ee9f8aaf77df1c6064785827 100644 (file)
@@ -338,6 +338,10 @@ static void disasm(uint32_t *buf, int sizedwords)
                case OPC_CALL:
                        fxn_idx(instr->call.uoff, true);
                        break;
                case OPC_CALL:
                        fxn_idx(instr->call.uoff, true);
                        break;
+               case OPC_SETSECURE:
+                       /* this implicitly jumps to pc + 3 if successful */
+                       label_idx(i + 3, true);
+                       break;
                default:
                        break;
                }
                default:
                        break;
                }
@@ -672,6 +676,18 @@ static void disasm(uint32_t *buf, int sizedwords)
                                printlbl("%s", label_name(instr->call.uoff, true));
                        }
                        break;
                                printlbl("%s", label_name(instr->call.uoff, true));
                        }
                        break;
+               case OPC_SETSECURE:
+                       /* Note: This seems to implicitly read the secure/not-secure state
+                        * to set from the low bit of $02, and implicitly jumps to pc + 3
+                        * (i.e. skipping the next two instructions) if it succeeds. We
+                        * print these implicit parameters to make reading the disassembly
+                        * easier.
+                        */
+                       if (instr->pad)
+                               printf("[%08x]  ; ", instrs[i]);
+                       printf("setsecure $02, #");
+                       printlbl("%s", label_name(i + 3, true));
+                       break;
                default:
                        printerr("[%08x]", instrs[i]);
                        printf("  ; op%02x ", opc);
                default:
                        printerr("[%08x]", instrs[i]);
                        printf("  ; op%02x ", opc);
index f78446011c2fa9c79e57f442723ffbea211b7815..077ae657d3cd514c14eee15023ee6e51a796411b 100644 (file)
@@ -82,6 +82,7 @@ extern YYSTYPE yylval;
 "jump"                            return TOKEN(T_OP_JUMP);
 "waitin"                          return TOKEN(T_OP_WAITIN);
 "preemptleave"                   return TOKEN(T_OP_PREEMPTLEAVE);
 "jump"                            return TOKEN(T_OP_JUMP);
 "waitin"                          return TOKEN(T_OP_WAITIN);
 "preemptleave"                   return TOKEN(T_OP_PREEMPTLEAVE);
+"setsecure"                      return TOKEN(T_OP_SETSECURE);
 "<<"                              return TOKEN(T_LSHIFT);
 "(rep)"                           return TOKEN(T_REP);
 
 "<<"                              return TOKEN(T_LSHIFT);
 "(rep)"                           return TOKEN(T_REP);
 
index 5eb6e6a6a14ff881a5682b636e12e7add7320683..7b2eebd410a8777f6994924efc72c775f1b071ae 100644 (file)
@@ -157,6 +157,7 @@ label(const char *str)
 %token <tok> T_OP_JUMP
 %token <tok> T_OP_WAITIN
 %token <tok> T_OP_PREEMPTLEAVE
 %token <tok> T_OP_JUMP
 %token <tok> T_OP_WAITIN
 %token <tok> T_OP_PREEMPTLEAVE
+%token <tok> T_OP_SETSECURE
 %token <tok> T_LSHIFT
 %token <tok> T_REP
 
 %token <tok> T_LSHIFT
 %token <tok> T_REP
 
@@ -245,6 +246,7 @@ branch_instr:      branch_op reg ',' T_BIT ',' T_LABEL_REF     { src1($2); bit($
 
 other_instr:       T_OP_CALL T_LABEL_REF { new_instr($1); label($2); }
 |                  T_OP_PREEMPTLEAVE T_LABEL_REF { new_instr($1); label($2); }
 
 other_instr:       T_OP_CALL T_LABEL_REF { new_instr($1); label($2); }
 |                  T_OP_PREEMPTLEAVE T_LABEL_REF { new_instr($1); label($2); }
+|                  T_OP_SETSECURE reg ',' T_LABEL_REF { new_instr($1); src1($2); label($4); }
 |                  T_OP_RET              { new_instr($1); }
 |                  T_OP_JUMP T_LABEL_REF { new_instr($1); label($2); }
 |                  T_OP_WAITIN           { new_instr($1); }
 |                  T_OP_RET              { new_instr($1); }
 |                  T_OP_JUMP T_LABEL_REF { new_instr($1); label($2); }
 |                  T_OP_WAITIN           { new_instr($1); }