From a2c14ac070b6703d3e395707ab7938aca4fe4fdb Mon Sep 17 00:00:00 2001 From: Connor Abbott Date: Mon, 17 Aug 2020 14:26:49 +0200 Subject: [PATCH] freedreno/afuc: Handle setsecure opcode Part-of: --- src/freedreno/afuc/afuc.h | 1 + src/freedreno/afuc/asm.c | 11 +++++++++++ src/freedreno/afuc/disasm.c | 16 ++++++++++++++++ src/freedreno/afuc/lexer.l | 1 + src/freedreno/afuc/parser.y | 2 ++ 5 files changed, 31 insertions(+) diff --git a/src/freedreno/afuc/afuc.h b/src/freedreno/afuc/afuc.h index 4f9e9d21815..a69690a56f2 100644 --- a/src/freedreno/afuc/afuc.h +++ b/src/freedreno/afuc/afuc.h @@ -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_SETSECURE = 0x3b, /* switch secure mode on/off */ } afuc_opc; diff --git a/src/freedreno/afuc/asm.c b/src/freedreno/afuc/asm.c index 56036be46f6..896a8555cf3 100644 --- a/src/freedreno/afuc/asm.c +++ b/src/freedreno/afuc/asm.c @@ -262,6 +262,17 @@ static void emit_instructions(int outfd) 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; diff --git a/src/freedreno/afuc/disasm.c b/src/freedreno/afuc/disasm.c index d170b152fad..5c86f4327da 100644 --- a/src/freedreno/afuc/disasm.c +++ b/src/freedreno/afuc/disasm.c @@ -338,6 +338,10 @@ static void disasm(uint32_t *buf, int sizedwords) 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; } @@ -672,6 +676,18 @@ static void disasm(uint32_t *buf, int sizedwords) 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); diff --git a/src/freedreno/afuc/lexer.l b/src/freedreno/afuc/lexer.l index f78446011c2..077ae657d3c 100644 --- a/src/freedreno/afuc/lexer.l +++ b/src/freedreno/afuc/lexer.l @@ -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); +"setsecure" return TOKEN(T_OP_SETSECURE); "<<" return TOKEN(T_LSHIFT); "(rep)" return TOKEN(T_REP); diff --git a/src/freedreno/afuc/parser.y b/src/freedreno/afuc/parser.y index 5eb6e6a6a14..7b2eebd410a 100644 --- a/src/freedreno/afuc/parser.y +++ b/src/freedreno/afuc/parser.y @@ -157,6 +157,7 @@ label(const char *str) %token T_OP_JUMP %token T_OP_WAITIN %token T_OP_PREEMPTLEAVE +%token T_OP_SETSECURE %token T_LSHIFT %token 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); } +| 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); } -- 2.30.2