gpu: nvgpu: unit: use allocated IO reg spaces

Statically initialized nvgpu_posix_io_reg_space structures are
used in test_fifo_setup_gv11b_reg_space to initialize register spaces.
If fifo, TSG and channel unit tests run concurrently, the same
register space structure can be registered multiple times for
different GPU contexts. This results in list corruption or
use of freed memory.

Use allocated register spaces instead.

Jira NVGPU-3943

Change-Id: I74c080f336e32149d2a378e2b15d37a2bd60ff71
Signed-off-by: Thomas Fleury <tfleury@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/2204062
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Debarshi Dutta <ddutta@nvidia.com>
Reviewed-by: Deepak Nibade <dnibade@nvidia.com>
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
This commit is contained in:
Thomas Fleury
2019-09-23 18:26:23 -04:00
committed by Alex Waterman
parent 10094b7091
commit f779eb8e9a

View File

@@ -33,6 +33,8 @@
#include "hal/fuse/fuse_gm20b.h" #include "hal/fuse/fuse_gm20b.h"
#include <nvgpu/hw/gv11b/hw_usermode_gv11b.h>
#include "nvgpu-fifo-gv11b.h" #include "nvgpu-fifo-gv11b.h"
u32 gv11b_fuse_regs[] = { u32 gv11b_fuse_regs[] = {
@@ -294,12 +296,6 @@ u32 gv11b_fuse_regs[] = {
/* 0x00021ff0 */ 0xbadf5040, 0xbadf5040, 0xbadf5040, 0xbadf5040, /* 0x00021ff0 */ 0xbadf5040, 0xbadf5040, 0xbadf5040, 0xbadf5040,
}; };
struct nvgpu_posix_io_reg_space gv11b_fuse_reg_space = {
.base = 0x00021000,
.size = sizeof(gv11b_fuse_regs),
.data = gv11b_fuse_regs,
};
u32 gv11b_master_regs[] = { u32 gv11b_master_regs[] = {
/* 0x00000000 */ 0x15b000a1, 0x00000000, 0x00000000, 0xbadf5040, /* 0x00000000 */ 0x15b000a1, 0x00000000, 0x00000000, 0xbadf5040,
/* 0x00000010 */ 0xbadf5040, 0xbadf5040, 0xbadf5040, 0xbadf5040, /* 0x00000010 */ 0xbadf5040, 0xbadf5040, 0xbadf5040, 0xbadf5040,
@@ -559,13 +555,6 @@ u32 gv11b_master_regs[] = {
/* 0x00000ff0 */ 0xbadf5040, 0xbadf5040, 0xbadf5040, 0xbadf5040, /* 0x00000ff0 */ 0xbadf5040, 0xbadf5040, 0xbadf5040, 0xbadf5040,
}; };
struct nvgpu_posix_io_reg_space gv11b_master_reg_space = {
.base = 0x00000000,
.size = sizeof(gv11b_master_regs),
.data = gv11b_master_regs,
};
u32 gv11b_top_regs[] = { u32 gv11b_top_regs[] = {
/* 0x00022400 */ 0x00010000, 0x00000000, 0x00000000, 0x00000000, /* 0x00022400 */ 0x00010000, 0x00000000, 0x00000000, 0x00000000,
/* 0x00022410 */ 0xbadf5040, 0xbadf5040, 0xbadf5040, 0x00000081, /* 0x00022410 */ 0xbadf5040, 0xbadf5040, 0xbadf5040, 0x00000081,
@@ -633,12 +622,6 @@ u32 gv11b_top_regs[] = {
/* 0x000227f0 */ 0x00000000, 0x00000000, 0x00000000, 0x00000000, /* 0x000227f0 */ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
}; };
struct nvgpu_posix_io_reg_space gv11b_top_reg_space = {
.base = 0x22400,
.size = sizeof(gv11b_top_regs),
.data = gv11b_top_regs,
};
u32 gv11b_fifo_regs[] = { u32 gv11b_fifo_regs[] = {
/* 0x00002000 */ 0x00000000, 0x00200003, 0x00000200, 0x0000c36f, /* 0x00002000 */ 0x00000000, 0x00200003, 0x00000200, 0x0000c36f,
/* 0x00002010 */ 0x0000000f, 0xbadf5040, 0xbadf5040, 0xbadf5040, /* 0x00002010 */ 0x0000000f, 0xbadf5040, 0xbadf5040, 0xbadf5040,
@@ -1154,12 +1137,6 @@ u32 gv11b_fifo_regs[] = {
/* 0x00003ff0 */ 0xbadf5040, 0xbadf5040, 0xbadf5040, 0xbadf5040, /* 0x00003ff0 */ 0xbadf5040, 0xbadf5040, 0xbadf5040, 0xbadf5040,
}; };
struct nvgpu_posix_io_reg_space gv11b_fifo_reg_space = {
.base = 0x2000,
.size = sizeof(gv11b_fifo_regs),
.data = gv11b_fifo_regs,
};
u32 gv11b_pbdma_regs[] = { u32 gv11b_pbdma_regs[] = {
/* 0x00040000 */ 0x00000003, 0x00000000, 0x1cd05e03, 0x00000008, /* 0x00040000 */ 0x00000003, 0x00000000, 0x1cd05e03, 0x00000008,
/* 0x00040010 */ 0x0000c36f, 0x00000003, 0x00408050, 0x0000001f, /* 0x00040010 */ 0x0000c36f, 0x00000003, 0x00408050, 0x0000001f,
@@ -9355,12 +9332,6 @@ u32 gv11b_pbdma_regs[] = {
/* 0x0005fff0 */ 0xbad00100, 0xbad00100, 0xbad00100, 0xbad00100, /* 0x0005fff0 */ 0xbad00100, 0xbad00100, 0xbad00100, 0xbad00100,
}; };
struct nvgpu_posix_io_reg_space gv11b_pbdma_reg_space = {
.base = 0x00040000,
.size = sizeof(gv11b_pbdma_regs),
.data = gv11b_pbdma_regs,
};
u32 gv11b_ccsr_regs[] = { u32 gv11b_ccsr_regs[] = {
/* 0x00800000 */ 0x00000000, 0x00000000, 0x00000000, 0x00000000, /* 0x00800000 */ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
/* 0x00800010 */ 0x00000000, 0x00000000, 0x00000000, 0x00000000, /* 0x00800010 */ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -13460,17 +13431,6 @@ u32 gv11b_ccsr_regs[] = {
/* 0x0080fff0 */ 0xbad00100, 0xbad00100, 0xbad00100, 0xbad00100, /* 0x0080fff0 */ 0xbad00100, 0xbad00100, 0xbad00100, 0xbad00100,
}; };
struct nvgpu_posix_io_reg_space gv11b_ccsr_reg_space = {
.base = 0x00800000,
.size = sizeof(gv11b_ccsr_regs),
.data = gv11b_ccsr_regs,
};
struct nvgpu_posix_io_reg_space gv11b_usermode_reg_space = {
.base = 0x00810000,
.size = 0x10000,
.data = NULL,
};
/* /*
* Mock I/O * Mock I/O
*/ */
@@ -13516,97 +13476,140 @@ static struct nvgpu_posix_io_callbacks test_reg_callbacks = {
.tegra_fuse_readl = tegra_fuse_readl_access_reg_fn, .tegra_fuse_readl = tegra_fuse_readl_access_reg_fn,
}; };
#define fifo_array_reg_space(x) sizeof(x)/sizeof(struct nvgpu_posix_io_reg_space)
struct nvgpu_posix_io_reg_space fifo_gv11b_initialized_reg_space[] = {
[0] = { /* FUSE */
.base = 0x00021000,
.size = sizeof(gv11b_fuse_regs),
.data = gv11b_fuse_regs,
},
[1] = { /* MASTER */
.base = 0x00000000,
.size = sizeof(gv11b_master_regs),
.data = gv11b_master_regs,
},
[2] = { /* TOP */
.base = 0x22400,
.size = sizeof(gv11b_top_regs),
.data = gv11b_top_regs,
},
[3] = { /* PBDMA */
.base = 0x00040000,
.size = sizeof(gv11b_pbdma_regs),
.data = gv11b_pbdma_regs,
},
[4] = { /* CCSR */
.base = 0x00800000,
.size = sizeof(gv11b_ccsr_regs),
.data = gv11b_ccsr_regs,
},
[5] = { /* FIFO */
.base = 0x2000,
.size = sizeof(gv11b_fifo_regs),
.data = gv11b_fifo_regs,
}
};
struct nvgpu_posix_io_reg_space gv11b_usermode_reg_space = {
.base = 0x00810000,
.size = 0x10000,
.data = NULL,
};
static void fifo_io_delete_initialized_reg_space(struct unit_module *m, struct gk20a *g)
{
u32 i = 0;
u32 arr_size = fifo_array_reg_space(fifo_gv11b_initialized_reg_space);
for (i = 0; i < arr_size; i++) {
u32 base = fifo_gv11b_initialized_reg_space[i].base;
nvgpu_posix_io_delete_reg_space(g, base);
}
}
static int fifo_io_add_initialized_reg_space(struct unit_module *m, struct gk20a *g)
{
int ret = 0;
u32 arr_size = fifo_array_reg_space(fifo_gv11b_initialized_reg_space);
u32 i = 0, j = 0;
u32 base, size;
struct nvgpu_posix_io_reg_space *reg_space;
for (i = 0; i < arr_size; i++) {
base = fifo_gv11b_initialized_reg_space[i].base;
size = fifo_gv11b_initialized_reg_space[i].size;
if (nvgpu_posix_io_add_reg_space(g, base, size) != 0) {
unit_err(m, "failed to add reg space for %08x\n", base);
ret = -ENOMEM;
goto clean_init_reg_space;
}
reg_space = nvgpu_posix_io_get_reg_space(g, base);
if (reg_space == NULL) {
unit_err(m, "failed to get reg space for %08x\n", base);
ret = -EINVAL;
goto clean_init_reg_space;
}
memcpy(reg_space->data, fifo_gv11b_initialized_reg_space[i].data, size);
}
return ret;
clean_init_reg_space:
for (j = 0; j < i; j++) {
base = fifo_gv11b_initialized_reg_space[j].base;
nvgpu_posix_io_delete_reg_space(g, base);
}
return ret;
}
int test_fifo_setup_gv11b_reg_space(struct unit_module *m, struct gk20a *g) int test_fifo_setup_gv11b_reg_space(struct unit_module *m, struct gk20a *g)
{ {
u32 i; u32 i;
struct nvgpu_posix_io_reg_space *reg_space;
/* Create register space */ /* Create register space */
nvgpu_posix_io_init_reg_space(g); nvgpu_posix_io_init_reg_space(g);
if (nvgpu_posix_io_register_reg_space(g, if (fifo_io_add_initialized_reg_space(m, g) != 0) {
&gv11b_master_reg_space) != 0) { unit_err(m, "failed to get initialized reg space\n");
unit_err(m, "%s: failed to create master register space\n",
__func__);
return UNIT_FAIL; return UNIT_FAIL;
} }
if (nvgpu_posix_io_register_reg_space(g, &gv11b_top_reg_space) != 0) { /* USERMODE reg space */
unit_err(m, "%s: failed to create top register space\n", if (nvgpu_posix_io_add_reg_space(g, usermode_cfg0_r(), 0x10000) != 0) {
__func__); unit_err(m, "Add USERMODE reg space failed!\n");
goto clean_up_master; goto clean_up_reg_space;
} }
if (nvgpu_posix_io_register_reg_space(g, &gv11b_fifo_reg_space) != 0) { reg_space = nvgpu_posix_io_get_reg_space(g, usermode_cfg0_r());
unit_err(m, "%s: failed to create fifo register space\n", if (reg_space == NULL) {
__func__); unit_err(m, "failed to get reg space for %08x\n",
goto clean_up_top; usermode_cfg0_r());
goto clean_up_reg_space;
} }
if (nvgpu_posix_io_register_reg_space(g, &gv11b_pbdma_reg_space) != 0) { for (i = 0U; i < reg_space->size / 4U; i++) {
unit_err(m, "%s: failed to create pbdma register space\n", reg_space->data[i] = 0xbadf1100;
__func__);
goto clean_up_fifo;
}
if (nvgpu_posix_io_register_reg_space(g, &gv11b_ccsr_reg_space) != 0) {
unit_err(m, "%s: failed to create ccsr register space\n",
__func__);
goto clean_up_pbdma;
}
if (nvgpu_posix_io_register_reg_space(g, &gv11b_fuse_reg_space) != 0) {
unit_err(m, "%s: failed to create fuse register space\n",
__func__);
goto clean_up_ccsr;
}
gv11b_usermode_reg_space.data = nvgpu_vzalloc(g,
gv11b_usermode_reg_space.size);
if (gv11b_usermode_reg_space.data == NULL) {
unit_err(m, "%s: failed to allocate usermode register space\n",
__func__);
goto clean_up_fuse;
}
for (i = 0U; i < gv11b_usermode_reg_space.size / 4U; i++) {
gv11b_usermode_reg_space.data[i] = 0xbadf1100;
}
if (nvgpu_posix_io_register_reg_space(g,
&gv11b_usermode_reg_space) != 0) {
unit_err(m, "%s: failed to create usermode register space\n",
__func__);
goto clean_up_usermode;
} }
(void)nvgpu_posix_register_io(g, &test_reg_callbacks); (void)nvgpu_posix_register_io(g, &test_reg_callbacks);
return 0; return 0;
clean_up_usermode: clean_up_reg_space:
nvgpu_vfree(g, gv11b_usermode_reg_space.data); nvgpu_posix_io_delete_reg_space(g, usermode_cfg0_r());
clean_up_fuse: fifo_io_delete_initialized_reg_space(m, g);
nvgpu_posix_io_unregister_reg_space(g, &gv11b_fuse_reg_space);
clean_up_ccsr:
nvgpu_posix_io_unregister_reg_space(g, &gv11b_ccsr_reg_space);
clean_up_pbdma:
nvgpu_posix_io_unregister_reg_space(g, &gv11b_pbdma_reg_space);
clean_up_fifo:
nvgpu_posix_io_unregister_reg_space(g, &gv11b_fifo_reg_space);
clean_up_top:
nvgpu_posix_io_unregister_reg_space(g, &gv11b_top_reg_space);
clean_up_master:
nvgpu_posix_io_unregister_reg_space(g, &gv11b_master_reg_space);
return -ENOMEM; return -ENOMEM;
} }
void test_fifo_cleanup_gv11b_reg_space(struct unit_module *m, struct gk20a *g) void test_fifo_cleanup_gv11b_reg_space(struct unit_module *m, struct gk20a *g)
{ {
nvgpu_posix_io_unregister_reg_space(g, &gv11b_master_reg_space); nvgpu_posix_io_delete_reg_space(g, usermode_cfg0_r());
nvgpu_posix_io_unregister_reg_space(g, &gv11b_top_reg_space); fifo_io_delete_initialized_reg_space(m, g);
nvgpu_posix_io_unregister_reg_space(g, &gv11b_fifo_reg_space);
nvgpu_posix_io_unregister_reg_space(g, &gv11b_pbdma_reg_space);
nvgpu_posix_io_unregister_reg_space(g, &gv11b_ccsr_reg_space);
nvgpu_vfree(g, gv11b_usermode_reg_space.data);
nvgpu_posix_io_unregister_reg_space(g, &gv11b_usermode_reg_space);
} }