gpu: nvgpu: remove debugger include from regops

Regops does not depend on debug session logically
We right now include debugger.h in regops_gk20a.c to extract
channel pointer from debug session and to check if session is for
profiling or not

Update exec_regops_gk20a() to receive channel pointer and profiler
flag directly as parameters, and remove dbg_session_gk20a from
parameter list

Remove ((!dbg_s->is_profiler) && (ch != NULL)) checks from
check_whitelists(). Caller of exec_regops_gk20a() already ensures
that we have context bound for debug session
Use only is_profiler boolean flag in this case which should be
sufficient

Remove (ch == NULL) check in check_whitelists() if regops is of
type gr_ctx. Instead move this check to earlier function call
in validate_reg_ops(). If we have non-zero context operation on
a profiler session, return error from validate_reg_ops()

Update all subsequent calls with appropriate parameter list

Remove debugger.h include from regops_gk20a.c

Jira NVGPU-620

Change-Id: If857c21da1a43a2230c1f7ef2cc2ad6640ff48d9
Signed-off-by: Deepak Nibade <dnibade@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1997868
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Deepak Nibade
2019-01-17 19:09:30 +05:30
committed by mobile promotions
parent 0ff5a49f45
commit b3b87cf303
6 changed files with 80 additions and 74 deletions

View File

@@ -1,7 +1,7 @@
/* /*
* Tegra GK20A GPU Debugger Driver Register Ops * Tegra GK20A GPU Debugger Driver Register Ops
* *
* Copyright (c) 2013-2018, NVIDIA CORPORATION. All rights reserved. * Copyright (c) 2013-2019, NVIDIA CORPORATION. All rights reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * copy of this software and associated documentation files (the "Software"),
@@ -25,7 +25,6 @@
#include "gr_gk20a.h" #include "gr_gk20a.h"
#include "regops_gk20a.h" #include "regops_gk20a.h"
#include <nvgpu/debugger.h>
#include <nvgpu/log.h> #include <nvgpu/log.h>
#include <nvgpu/bsearch.h> #include <nvgpu/bsearch.h>
#include <nvgpu/bug.h> #include <nvgpu/bug.h>
@@ -82,22 +81,21 @@ static bool gr_context_info_available(struct gr_gk20a *gr)
} }
static bool validate_reg_ops(struct dbg_session_gk20a *dbg_s, static bool validate_reg_ops(struct gk20a *g,
u32 *ctx_rd_count, u32 *ctx_wr_count, u32 *ctx_rd_count, u32 *ctx_wr_count,
struct nvgpu_dbg_reg_op *ops, struct nvgpu_dbg_reg_op *ops,
u32 op_count); u32 op_count,
bool is_profiler);
int exec_regops_gk20a(struct gk20a *g,
int exec_regops_gk20a(struct dbg_session_gk20a *dbg_s, struct channel_gk20a *ch,
struct nvgpu_dbg_reg_op *ops, struct nvgpu_dbg_reg_op *ops,
u64 num_ops, u64 num_ops,
bool is_profiler,
bool *is_current_ctx) bool *is_current_ctx)
{ {
int err = 0; int err = 0;
unsigned int i; unsigned int i;
struct channel_gk20a *ch = NULL;
struct gk20a *g = dbg_s->g;
/*struct gr_gk20a *gr = &g->gr;*/
u32 data32_lo = 0, data32_hi = 0; u32 data32_lo = 0, data32_hi = 0;
u32 ctx_rd_count = 0, ctx_wr_count = 0; u32 ctx_rd_count = 0, ctx_wr_count = 0;
bool skip_read_lo, skip_read_hi; bool skip_read_lo, skip_read_hi;
@@ -105,8 +103,6 @@ int exec_regops_gk20a(struct dbg_session_gk20a *dbg_s,
nvgpu_log(g, gpu_dbg_fn | gpu_dbg_gpu_dbg, " "); nvgpu_log(g, gpu_dbg_fn | gpu_dbg_gpu_dbg, " ");
ch = nvgpu_dbg_gpu_get_session_channel(dbg_s);
/* For vgpu, the regops routines need to be handled in the /* For vgpu, the regops routines need to be handled in the
* context of the server and support for that does not exist. * context of the server and support for that does not exist.
* *
@@ -119,9 +115,8 @@ int exec_regops_gk20a(struct dbg_session_gk20a *dbg_s,
return -ENOSYS; return -ENOSYS;
} }
ok = validate_reg_ops(dbg_s, ok = validate_reg_ops(g, &ctx_rd_count, &ctx_wr_count,
&ctx_rd_count, &ctx_wr_count, ops, num_ops, is_profiler);
ops, num_ops);
if (!ok) { if (!ok) {
nvgpu_err(g, "invalid op(s)"); nvgpu_err(g, "invalid op(s)");
err = -EINVAL; err = -EINVAL;
@@ -236,8 +231,7 @@ int exec_regops_gk20a(struct dbg_session_gk20a *dbg_s,
} }
static int validate_reg_op_info(struct dbg_session_gk20a *dbg_s, static int validate_reg_op_info(struct nvgpu_dbg_reg_op *op)
struct nvgpu_dbg_reg_op *op)
{ {
int err = 0; int err = 0;
@@ -276,14 +270,12 @@ static int validate_reg_op_info(struct dbg_session_gk20a *dbg_s,
return err; return err;
} }
static bool check_whitelists(struct dbg_session_gk20a *dbg_s, static bool check_whitelists(struct gk20a *g,
struct nvgpu_dbg_reg_op *op, u32 offset) struct nvgpu_dbg_reg_op *op,
u32 offset,
bool is_profiler)
{ {
struct gk20a *g = dbg_s->g;
bool valid = false; bool valid = false;
struct channel_gk20a *ch;
ch = nvgpu_dbg_gpu_get_session_channel(dbg_s);
if (op->type == REGOP(TYPE_GLOBAL)) { if (op->type == REGOP(TYPE_GLOBAL)) {
/* search global list */ /* search global list */
@@ -294,8 +286,8 @@ static bool check_whitelists(struct dbg_session_gk20a *dbg_s,
sizeof(*g->ops.regops.get_global_whitelist_ranges()), sizeof(*g->ops.regops.get_global_whitelist_ranges()),
regop_bsearch_range_cmp) != NULL); regop_bsearch_range_cmp) != NULL);
/* if debug session and channel is bound search context list */ /* if debug session, search context list */
if ((!valid) && (!dbg_s->is_profiler) && (ch != NULL)) { if ((!valid) && (!is_profiler)) {
/* binary search context list */ /* binary search context list */
valid = (g->ops.regops.get_context_whitelist_ranges != NULL) && valid = (g->ops.regops.get_context_whitelist_ranges != NULL) &&
(bsearch(&offset, (bsearch(&offset,
@@ -305,21 +297,14 @@ static bool check_whitelists(struct dbg_session_gk20a *dbg_s,
regop_bsearch_range_cmp) != NULL); regop_bsearch_range_cmp) != NULL);
} }
/* if debug session and channel is bound search runcontrol list */ /* if debug session, search runcontrol list */
if ((!valid) && (!dbg_s->is_profiler) && (ch != NULL)) { if ((!valid) && (!is_profiler)) {
valid = (g->ops.regops.get_runcontrol_whitelist != NULL) && valid = (g->ops.regops.get_runcontrol_whitelist != NULL) &&
linear_search(offset, linear_search(offset,
g->ops.regops.get_runcontrol_whitelist(), g->ops.regops.get_runcontrol_whitelist(),
g->ops.regops.get_runcontrol_whitelist_count()); g->ops.regops.get_runcontrol_whitelist_count());
} }
} else if (op->type == REGOP(TYPE_GR_CTX)) { } else if (op->type == REGOP(TYPE_GR_CTX)) {
/* it's a context-relative op */
if (ch == NULL) {
nvgpu_err(dbg_s->g, "can't perform ctx regop unless bound");
op->status = REGOP(STATUS_UNSUPPORTED_OP);
return valid;
}
/* binary search context list */ /* binary search context list */
valid = (g->ops.regops.get_context_whitelist_ranges != NULL) && valid = (g->ops.regops.get_context_whitelist_ranges != NULL) &&
(bsearch(&offset, (bsearch(&offset,
@@ -328,8 +313,8 @@ static bool check_whitelists(struct dbg_session_gk20a *dbg_s,
sizeof(*g->ops.regops.get_context_whitelist_ranges()), sizeof(*g->ops.regops.get_context_whitelist_ranges()),
regop_bsearch_range_cmp) != NULL); regop_bsearch_range_cmp) != NULL);
/* if debug session and channel is bound search runcontrol list */ /* if debug session, search runcontrol list */
if ((!valid) && (!dbg_s->is_profiler) && (ch != NULL)) { if ((!valid) && (!is_profiler)) {
valid = (g->ops.regops.get_runcontrol_whitelist != NULL) && valid = (g->ops.regops.get_runcontrol_whitelist != NULL) &&
linear_search(offset, linear_search(offset,
g->ops.regops.get_runcontrol_whitelist(), g->ops.regops.get_runcontrol_whitelist(),
@@ -347,8 +332,9 @@ static bool check_whitelists(struct dbg_session_gk20a *dbg_s,
} }
/* note: the op here has already been through validate_reg_op_info */ /* note: the op here has already been through validate_reg_op_info */
static int validate_reg_op_offset(struct dbg_session_gk20a *dbg_s, static int validate_reg_op_offset(struct gk20a *g,
struct nvgpu_dbg_reg_op *op) struct nvgpu_dbg_reg_op *op,
bool is_profiler)
{ {
int err; int err;
u32 buf_offset_lo, buf_offset_addr, num_offsets, offset; u32 buf_offset_lo, buf_offset_addr, num_offsets, offset;
@@ -359,18 +345,18 @@ static int validate_reg_op_offset(struct dbg_session_gk20a *dbg_s,
/* support only 24-bit 4-byte aligned offsets */ /* support only 24-bit 4-byte aligned offsets */
if ((offset & 0xFF000003U) != 0U) { if ((offset & 0xFF000003U) != 0U) {
nvgpu_err(dbg_s->g, "invalid regop offset: 0x%x", offset); nvgpu_err(g, "invalid regop offset: 0x%x", offset);
op->status |= REGOP(STATUS_INVALID_OFFSET); op->status |= REGOP(STATUS_INVALID_OFFSET);
return -EINVAL; return -EINVAL;
} }
valid = check_whitelists(dbg_s, op, offset); valid = check_whitelists(g, op, offset, is_profiler);
if ((op->op == REGOP(READ_64) || op->op == REGOP(WRITE_64)) && valid) { if ((op->op == REGOP(READ_64) || op->op == REGOP(WRITE_64)) && valid) {
valid = check_whitelists(dbg_s, op, offset + 4U); valid = check_whitelists(g, op, offset + 4U, is_profiler);
} }
if (valid && (op->type != REGOP(TYPE_GLOBAL))) { if (valid && (op->type != REGOP(TYPE_GLOBAL))) {
err = gr_gk20a_get_ctx_buffer_offsets(dbg_s->g, err = gr_gk20a_get_ctx_buffer_offsets(g,
op->offset, op->offset,
1, 1,
&buf_offset_lo, &buf_offset_lo,
@@ -379,13 +365,12 @@ static int validate_reg_op_offset(struct dbg_session_gk20a *dbg_s,
op->type == REGOP(TYPE_GR_CTX_QUAD), op->type == REGOP(TYPE_GR_CTX_QUAD),
op->quad); op->quad);
if (err != 0) { if (err != 0) {
err = gr_gk20a_get_pm_ctx_buffer_offsets(dbg_s->g, err = gr_gk20a_get_pm_ctx_buffer_offsets(g,
op->offset, op->offset,
1, 1,
&buf_offset_lo, &buf_offset_lo,
&buf_offset_addr, &buf_offset_addr,
&num_offsets); &num_offsets);
if (err != 0) { if (err != 0) {
op->status |= REGOP(STATUS_INVALID_OFFSET); op->status |= REGOP(STATUS_INVALID_OFFSET);
return -EINVAL; return -EINVAL;
@@ -398,7 +383,7 @@ static int validate_reg_op_offset(struct dbg_session_gk20a *dbg_s,
} }
if (!valid) { if (!valid) {
nvgpu_err(dbg_s->g, "invalid regop offset: 0x%x", offset); nvgpu_err(g, "invalid regop offset: 0x%x", offset);
op->status |= REGOP(STATUS_INVALID_OFFSET); op->status |= REGOP(STATUS_INVALID_OFFSET);
return -EINVAL; return -EINVAL;
} }
@@ -406,21 +391,23 @@ static int validate_reg_op_offset(struct dbg_session_gk20a *dbg_s,
return 0; return 0;
} }
static bool validate_reg_ops(struct dbg_session_gk20a *dbg_s, static bool validate_reg_ops(struct gk20a *g,
u32 *ctx_rd_count, u32 *ctx_wr_count, u32 *ctx_rd_count, u32 *ctx_wr_count,
struct nvgpu_dbg_reg_op *ops, struct nvgpu_dbg_reg_op *ops,
u32 op_count) u32 op_count,
bool is_profiler)
{ {
u32 i; u32 i;
bool ok = true; bool ok = true;
struct gk20a *g = dbg_s->g; bool gr_ctx_ops = false;
/* keep going until the end so every op can get /* keep going until the end so every op can get
* a separate error code if needed */ * a separate error code if needed */
for (i = 0; i < op_count; i++) { for (i = 0; i < op_count; i++) {
if (validate_reg_op_info(dbg_s, &ops[i]) != 0) { if (validate_reg_op_info(&ops[i]) != 0) {
ok = false; ok = false;
break;
} }
if (reg_op_is_gr_ctx(ops[i].type)) { if (reg_op_is_gr_ctx(ops[i].type)) {
@@ -429,18 +416,30 @@ static bool validate_reg_ops(struct dbg_session_gk20a *dbg_s,
} else { } else {
(*ctx_wr_count)++; (*ctx_wr_count)++;
} }
gr_ctx_ops = true;
}
/* context operations are not valid on profiler session */
if (gr_ctx_ops && is_profiler) {
ok = false;
break;
} }
/* if "allow_all" flag enabled, dont validate offset */ /* if "allow_all" flag enabled, dont validate offset */
if (!g->allow_all) { if (!g->allow_all) {
if (validate_reg_op_offset(dbg_s, &ops[i]) != 0) { if (validate_reg_op_offset(g, &ops[i],
is_profiler) != 0) {
ok = false; ok = false;
break;
} }
} }
} }
if (ok) {
nvgpu_log(g, gpu_dbg_gpu_dbg, "ctx_wrs:%d ctx_rds:%d", nvgpu_log(g, gpu_dbg_gpu_dbg, "ctx_wrs:%d ctx_rds:%d",
*ctx_wr_count, *ctx_rd_count); *ctx_wr_count, *ctx_rd_count);
}
return ok; return ok;
} }

View File

@@ -1,7 +1,7 @@
/* /*
* Tegra GK20A GPU Debugger Driver Register Ops * Tegra GK20A GPU Debugger Driver Register Ops
* *
* Copyright (c) 2013-2018, NVIDIA CORPORATION. All rights reserved. * Copyright (c) 2013-2019, NVIDIA CORPORATION. All rights reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * copy of this software and associated documentation files (the "Software"),
@@ -75,9 +75,11 @@ struct regop_offset_range {
u32 count:8; u32 count:8;
}; };
int exec_regops_gk20a(struct dbg_session_gk20a *dbg_s, int exec_regops_gk20a(struct gk20a *g,
struct channel_gk20a *ch,
struct nvgpu_dbg_reg_op *ops, struct nvgpu_dbg_reg_op *ops,
u64 num_ops, u64 num_ops,
bool is_profiler,
bool *is_current_ctx); bool *is_current_ctx);
/* turn seriously unwieldy names -> something shorter */ /* turn seriously unwieldy names -> something shorter */

View File

@@ -1284,9 +1284,11 @@ struct gpu_ops {
bool support_vfe; bool support_vfe;
} pmu_perf; } pmu_perf;
struct { struct {
int (*exec_regops)(struct dbg_session_gk20a *dbg_s, int (*exec_regops)(struct gk20a *g,
struct channel_gk20a *ch,
struct nvgpu_dbg_reg_op *ops, struct nvgpu_dbg_reg_op *ops,
u64 num_ops, u64 num_ops,
bool is_profiler,
bool *is_current_ctx); bool *is_current_ctx);
const struct regop_offset_range* ( const struct regop_offset_range* (
*get_global_whitelist_ranges)(void); *get_global_whitelist_ranges)(void);

View File

@@ -1,7 +1,7 @@
/* /*
* Tegra GK20A GPU Debugger/Profiler Driver * Tegra GK20A GPU Debugger/Profiler Driver
* *
* Copyright (c) 2017-2018, NVIDIA CORPORATION. All rights reserved. * Copyright (c) 2017-2019, NVIDIA CORPORATION. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -882,8 +882,9 @@ static int nvgpu_ioctl_channel_reg_ops(struct dbg_session_gk20a *dbg_s,
if (err) if (err)
break; break;
err = g->ops.regops.exec_regops( err = g->ops.regops.exec_regops(g, ch,
dbg_s, g->dbg_regops_tmp_buf, num_ops, &is_current_ctx); g->dbg_regops_tmp_buf, num_ops,
dbg_s->is_profiler, &is_current_ctx);
if (err) { if (err) {
break; break;

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015-2018, NVIDIA CORPORATION. All rights reserved. * Copyright (c) 2015-2019, NVIDIA CORPORATION. All rights reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * copy of this software and associated documentation files (the "Software"),
@@ -32,19 +32,19 @@
#include "gk20a/regops_gk20a.h" #include "gk20a/regops_gk20a.h"
#include "dbg_vgpu.h" #include "dbg_vgpu.h"
int vgpu_exec_regops(struct dbg_session_gk20a *dbg_s, int vgpu_exec_regops(struct gk20a *g,
struct channel_gk20a *ch,
struct nvgpu_dbg_reg_op *ops, struct nvgpu_dbg_reg_op *ops,
u64 num_ops, u64 num_ops,
bool is_profiler,
bool *is_current_ctx) bool *is_current_ctx)
{ {
struct channel_gk20a *ch;
struct tegra_vgpu_cmd_msg msg; struct tegra_vgpu_cmd_msg msg;
struct tegra_vgpu_reg_ops_params *p = &msg.params.reg_ops; struct tegra_vgpu_reg_ops_params *p = &msg.params.reg_ops;
void *oob; void *oob;
size_t oob_size, ops_size; size_t oob_size, ops_size;
void *handle = NULL; void *handle = NULL;
int err = 0; int err = 0;
struct gk20a *g = dbg_s->g;
nvgpu_log_fn(g, " "); nvgpu_log_fn(g, " ");
BUG_ON(sizeof(*ops) != sizeof(struct tegra_vgpu_reg_op)); BUG_ON(sizeof(*ops) != sizeof(struct tegra_vgpu_reg_op));
@@ -64,11 +64,10 @@ int vgpu_exec_regops(struct dbg_session_gk20a *dbg_s,
nvgpu_memcpy((u8 *)oob, (u8 *)ops, ops_size); nvgpu_memcpy((u8 *)oob, (u8 *)ops, ops_size);
msg.cmd = TEGRA_VGPU_CMD_REG_OPS; msg.cmd = TEGRA_VGPU_CMD_REG_OPS;
msg.handle = vgpu_get_handle(dbg_s->g); msg.handle = vgpu_get_handle(g);
ch = nvgpu_dbg_gpu_get_session_channel(dbg_s);
p->handle = ch ? ch->virt_ctx : 0; p->handle = ch ? ch->virt_ctx : 0;
p->num_ops = num_ops; p->num_ops = num_ops;
p->is_profiler = dbg_s->is_profiler; p->is_profiler = is_profiler;
err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg)); err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
err = err ? err : msg.ret; err = err ? err : msg.ret;
if (err == 0) { if (err == 0) {

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017-2018, NVIDIA CORPORATION. All rights reserved. * Copyright (c) 2017-2019, NVIDIA CORPORATION. All rights reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * copy of this software and associated documentation files (the "Software"),
@@ -27,10 +27,13 @@ struct dbg_session_gk20a;
struct nvgpu_dbg_reg_op; struct nvgpu_dbg_reg_op;
struct dbg_profiler_object_data; struct dbg_profiler_object_data;
struct gk20a; struct gk20a;
struct channel_gk20a;
int vgpu_exec_regops(struct dbg_session_gk20a *dbg_s, int vgpu_exec_regops(struct gk20a *g,
struct channel_gk20a *ch,
struct nvgpu_dbg_reg_op *ops, struct nvgpu_dbg_reg_op *ops,
u64 num_ops, u64 num_ops,
bool is_profiler,
bool *is_current_ctx); bool *is_current_ctx);
int vgpu_dbg_set_powergate(struct dbg_session_gk20a *dbg_s, bool disable_powergate); int vgpu_dbg_set_powergate(struct dbg_session_gk20a *dbg_s, bool disable_powergate);
bool vgpu_check_and_set_global_reservation( bool vgpu_check_and_set_global_reservation(