freedreno/decode: Add code to extent pkt processing with Lua

Setting up a new `iL` `lua_State` in which `r` is injected as
the equivalent to `rnn.init(<gpu>)` and a `priv` library allows
accessing extra functionality (not available to user provided
scripts) currently just allowing writing to registers.

Signed-off-by: Karmjit Mahil <karmjit.mahil@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/38001>
This commit is contained in:
Karmjit Mahil
2025-10-24 10:37:17 +01:00
committed by Marge Bot
parent 8825c91dcb
commit 265aa40a8a
8 changed files with 212 additions and 52 deletions
+9
View File
@@ -875,6 +875,15 @@ cffdec_init(const struct cffdec_options *_options)
default:
errx(-1, "unsupported generation: %u", options->info->chip);
}
internal_lua_pkt_handler_load();
internal_lua_pkt_handler_init_rnn(rnn);
}
void
cffdec_finish(void)
{
internal_lua_pkt_handler_finish();
}
const char *
+1
View File
@@ -112,6 +112,7 @@ uint32_t * parse_cp_indirect(uint32_t *dwords, uint32_t sizedwords,
uint64_t *ibaddr, uint32_t *ibsize);
void reset_regs(void);
void cffdec_init(const struct cffdec_options *options);
void cffdec_finish(void);
void dump_register_val(struct regacc *r, int level);
void dump_commands(uint32_t *dwords, uint32_t sizedwords, int level);
@@ -0,0 +1,3 @@
-- SPDX-License-Identifier: MIT
-- `r` is predefined in the environment and is the equivalent of rnn.init(<gpu>)
+3
View File
@@ -140,6 +140,8 @@ main(int argc, char **argv)
interactive = isatty(STDOUT_FILENO);
internal_lua_pkt_handler_load();
options.color = interactive;
while ((c = getopt_long(argc, argv, "vsaS:E:F:D:e:L:q:h", opts, NULL)) !=
@@ -348,6 +350,7 @@ handle_file(const char *filename, int start, int end, int draw)
}
script_end_cmdstream();
cffdec_finish();
reset_buffers();
+3
View File
@@ -20,6 +20,7 @@
#include "crashdec.h"
#include "cffdec.h"
static FILE *in;
bool verbose;
@@ -1187,6 +1188,8 @@ cleanup(void)
if (interactive) {
pager_close();
}
cffdec_finish();
}
int
+39 -27
View File
@@ -5,6 +5,13 @@ if with_tests
diff = find_program('diff')
endif
cffdump_pkt_handler_h = custom_target(
'cffdump-pkt-handler.h',
input : [files_xxd, 'cffdump-pkt-handler.lua'],
output : 'cffdump-pkt-handler.h',
command : [prog_python, '@INPUT@', '@OUTPUT@', '-n', 'cffdump_pkt_handler_lua_src'],
)
# Shared cmdstream decoding:
libfreedreno_cffdec = static_library(
'freedreno_cffdec',
@@ -17,7 +24,10 @@ libfreedreno_cffdec = static_library(
'pager.h',
'rnnutil.c',
'rnnutil.h',
'script.c',
'script.h',
'util.h',
cffdump_pkt_handler_h,
],
include_directories: [
inc_freedreno,
@@ -27,7 +37,9 @@ libfreedreno_cffdec = static_library(
],
c_args : [ no_override_init_args ],
gnu_symbol_visibility: 'hidden',
dependencies: [],
dependencies: [
dep_lua,
],
link_with: [
libfreedreno_rnn,
libfreedreno_ir2, # for disasm_a2xx
@@ -152,8 +164,6 @@ if dep_lua.found() and dep_libarchive.found()
'cffdump',
[
'cffdump.c',
'script.c',
'script.h'
],
include_directories: [
inc_freedreno,
@@ -174,6 +184,32 @@ if dep_lua.found() and dep_libarchive.found()
install: install_fd_decode_tools,
)
crashdec = executable(
'crashdec',
[
'crashdec.c',
'crashdec.h',
'crashdec-hfi.c',
'crashdec-mempool.c',
'crashdec-prefetch.c',
],
include_directories: [
inc_freedreno,
inc_freedreno_rnn,
inc_include,
inc_src,
],
gnu_symbol_visibility: 'hidden',
dependencies: [
dep_lua,
],
link_with: [
libfreedreno_cffdec,
],
build_by_default: with_tools.contains('freedreno'),
install: install_fd_decode_tools,
)
if with_tests
# dump only a single frame, and single tile pass, to keep the
# reference output size managable
@@ -209,30 +245,6 @@ else
warning('lua or libarchive not found, not building cffdump')
endif
crashdec = executable(
'crashdec',
[
'crashdec.c',
'crashdec.h',
'crashdec-hfi.c',
'crashdec-mempool.c',
'crashdec-prefetch.c',
],
include_directories: [
inc_freedreno,
inc_freedreno_rnn,
inc_include,
inc_src,
],
gnu_symbol_visibility: 'hidden',
dependencies: [],
link_with: [
libfreedreno_cffdec,
],
build_by_default: with_tools.contains('freedreno'),
install: install_fd_decode_tools,
)
dumpregs = executable(
'dumpregs',
[ 'dumpregs.c' ],
+142 -23
View File
@@ -20,10 +20,12 @@
#include "util/u_math.h"
#include "cffdec.h"
#include "cffdump-pkt-handler.h"
#include "rnnutil.h"
#include "script.h"
static lua_State *L;
static lua_State *iL;
#if 0
#define DBG(fmt, ...) \
@@ -547,6 +549,26 @@ static const struct luaL_Reg l_regs[] = {
{NULL, NULL} /* sentinel */
};
/* Expose the private functionality to the internal pkt enviroment as a "priv"
* library:
*/
static int
l_priv_reg_set(lua_State *L)
{
uint32_t regbase = (uint32_t)lua_tonumber(L, 1);
uint32_t regval = (uint32_t)lua_tonumber(L, 2);
reg_set(regbase, regval);
return 1;
}
static const struct luaL_Reg l_priv[] = {
{"reg_set", l_priv_reg_set},
{NULL, NULL} /* sentinel */
};
/* Expose API to lookup snapshot buffers:
*/
@@ -576,11 +598,20 @@ static const struct luaL_Reg l_bos[] = {
};
static void
openlib(const char *lib, const luaL_Reg *reg)
openlib(lua_State *state, const char *lib, const luaL_Reg *reg)
{
lua_newtable(L);
luaL_setfuncs(L, reg, 0);
lua_setglobal(L, lib);
lua_newtable(state);
luaL_setfuncs(state, reg, 0);
lua_setglobal(state, lib);
}
static void
common_libs(lua_State *state)
{
luaL_openlibs(state);
openlib(state, "bos", l_bos);
openlib(state, "regs", l_regs);
openlib(state, "rnn", l_rnn);
}
/* called at start to load the script: */
@@ -592,10 +623,7 @@ script_load(const char *file)
assert(!L);
L = luaL_newstate();
luaL_openlibs(L);
openlib("bos", l_bos);
openlib("regs", l_regs);
openlib("rnn", l_rnn);
common_libs(L);
ret = luaL_loadfile(L, file);
if (ret)
@@ -608,6 +636,48 @@ script_load(const char *file)
return 0;
}
void
internal_lua_pkt_handler_load(void)
{
int ret;
if (iL)
return;
iL = luaL_newstate();
common_libs(iL);
openlib(iL, "priv", l_priv);
ret = luaL_loadstring(iL, cffdump_pkt_handler_lua_src);
if (ret) {
fprintf(stderr, "%s\n", lua_tostring(iL, -1));
exit(1);
}
ret = lua_pcall(iL, 0, LUA_MULTRET, 0);
if (ret) {
fprintf(stderr, "%s\n", lua_tostring(iL, -1));
exit(1);
}
}
void
internal_lua_pkt_handler_init_rnn(struct rnn *rnn)
{
struct rnndec *rnndec = lua_newuserdata(iL, sizeof(*rnndec));
rnndec->base = *rnn;
rnndec->sizedwords = 0;
luaL_newmetatable(iL, "rnnmeta");
luaL_setfuncs(iL, l_meta_rnn, 0);
lua_pop(iL, 1);
luaL_setmetatable(iL, "rnnmeta");
lua_setglobal(iL, "r");
}
/* called at start of each cmdstream file: */
void
script_start_cmdstream(const char *name)
@@ -698,22 +768,24 @@ static const struct luaL_Reg l_meta_rnn_dom[] = {
/* called to general pm4 packet decoding, such as texture/sampler state
*/
void
script_packet(uint32_t *dwords, uint32_t sizedwords, struct rnn *rnn,
struct rnndomain *dom)
static bool
handle_packet_setup(lua_State *state, uint32_t *dwords, uint32_t sizedwords,
struct rnn *rnn, struct rnndomain *dom)
{
if (!L)
return;
if (!state)
return false;
lua_getglobal(L, dom->name);
assert(state == L || state == iL);
lua_getglobal(state, dom->name);
/* if no handler for the packet, just ignore it: */
if (!lua_isfunction(L, -1)) {
lua_pop(L, 1);
return;
if (!lua_isfunction(state, -1)) {
lua_pop(state, 1);
return false;
}
struct rnndec *rnndec = lua_newuserdata(L, sizeof(*rnndec));
struct rnndec *rnndec = lua_newuserdata(state, sizeof(*rnndec));
rnndec->base = *rnn;
rnndec->base.dom[0] = dom;
@@ -721,18 +793,55 @@ script_packet(uint32_t *dwords, uint32_t sizedwords, struct rnn *rnn,
rnndec->dwords = dwords;
rnndec->sizedwords = sizedwords;
luaL_newmetatable(L, "rnnmetadom");
luaL_setfuncs(L, l_meta_rnn_dom, 0);
lua_pop(L, 1);
luaL_newmetatable(state, "rnnmetadom");
luaL_setfuncs(state, l_meta_rnn_dom, 0);
lua_pop(state, 1);
luaL_setmetatable(L, "rnnmetadom");
luaL_setmetatable(state, "rnnmetadom");
lua_pushnumber(L, sizedwords);
lua_pushnumber(state, sizedwords);
return true;
}
void
script_packet(uint32_t *dwords, uint32_t sizedwords, struct rnn *rnn,
struct rnndomain *dom)
{
bool ret;
ret = handle_packet_setup(L, dwords, sizedwords, rnn, dom);
if (!ret)
return;
if (lua_pcall(L, 2, 0, 0) != 0)
error("error running function `f': %s\n");
}
const char *
internal_packet(uint32_t *dwords, uint32_t sizedwords, struct rnn *rnn,
struct rnndomain *dom)
{
bool ret;
ret = handle_packet_setup(iL, dwords, sizedwords, rnn, dom);
if (!ret)
return NULL;
/* 2 args, 1 result */
if (lua_pcall(iL, 2, 1, 0) != 0) {
fprintf(stderr, "error running function `f': %s\n",
lua_tostring(iL, -1));
exit(1);
}
char *str;
asprintf(&str, "%s", lua_tostring(iL, -1));
lua_pop(iL, 1);
return str;
}
/* helper to call fxn that takes and returns void: */
static void
simple_call(const char *name)
@@ -786,3 +895,13 @@ script_finish(void)
lua_close(L);
L = NULL;
}
void
internal_lua_pkt_handler_finish(void)
{
if (!iL)
return;
lua_close(iL);
iL = NULL;
}
+12 -2
View File
@@ -18,8 +18,14 @@
#ifdef ENABLE_SCRIPTING
struct rnn;
struct rnndomain;
/* called at start to load the script: */
int script_load(const char *file);
/* called at start to load internal pkt handlers: */
void internal_lua_pkt_handler_load(void);
void internal_lua_pkt_handler_init_rnn(struct rnn *rnn);
/* called at start of each cmdstream file: */
void script_start_cmdstream(const char *name);
@@ -30,13 +36,16 @@ void script_start_cmdstream(const char *name);
__attribute__((weak))
void script_draw(const char *primtype, uint32_t nindx);
struct rnn;
struct rnndomain;
__attribute__((weak))
void script_packet(uint32_t *dwords, uint32_t sizedwords,
struct rnn *rnn,
struct rnndomain *dom);
__attribute__((weak))
const char * internal_packet(uint32_t *dwords, uint32_t sizedwords,
struct rnn *rnn,
struct rnndomain *dom);
/* maybe at some point it is interesting to add additional script
* hooks for CP_EVENT_WRITE, etc?
*/
@@ -49,6 +58,7 @@ void script_end_submit(void);
/* called after last cmdstream file: */
void script_finish(void);
void internal_lua_pkt_handler_finish(void);
#else
// TODO no-op stubs..