Open source GPL/LGPL release

This commit is contained in:
svcmobrel-release
2025-12-19 15:25:44 -08:00
commit 9fc87a7ec7
2261 changed files with 576825 additions and 0 deletions

View File

@@ -0,0 +1,26 @@
# Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
.SUFFIXES:
OBJS = nvgpu_mem.o
MODULE = nvgpu_mem
include ../../Makefile.units

View File

@@ -0,0 +1,35 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
# tmake for SW Mobile component makefile
#
###############################################################################
NVGPU_UNIT_NAME=nvgpu_mem
include $(NV_COMPONENT_DIR)/../../Makefile.units.common.interface.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,35 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
# tmake for SW Mobile component makefile
#
###############################################################################
NVGPU_UNIT_NAME=nvgpu_mem
include $(NV_COMPONENT_DIR)/../../Makefile.units.common.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,35 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
# tmake for SW Mobile component makefile
#
###############################################################################
NVGPU_UNIT_NAME=nvgpu_mem
include $(NV_COMPONENT_DIR)/../../../Makefile.units.common.interface.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,38 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
# tmake for SW Mobile component makefile
#
###############################################################################
NVGPU_UNIT_NAME=nvgpu_mem
NVGPU_UNIT_SRCS=$(NV_COMPONENT_DIR)/../nvgpu_mem.c
CONFIG_NVGPU_DGPU := 1
include $(NV_COMPONENT_DIR)/../../../Makefile.units.common.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,736 @@
/*
* Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <stdlib.h>
#include <unit/io.h>
#include <unit/unit.h>
#include <nvgpu/nvgpu_mem.h>
#include <nvgpu/nvgpu_sgt.h>
#include <nvgpu/page_allocator.h>
#include <nvgpu/pramin.h>
#include <nvgpu/gk20a.h>
#include <nvgpu/sizes.h>
#include <nvgpu/dma.h>
#include <nvgpu/posix/io.h>
#include <nvgpu/posix/posix-fault-injection.h>
#include <os/posix/os_posix.h>
#include <hal/mm/gmmu/gmmu_gp10b.h>
#include <hal/pramin/pramin_init.h>
#include <hal/bus/bus_gk20a.h>
#include <nvgpu/hw/gk20a/hw_pram_gk20a.h>
#include <nvgpu/hw/gk20a/hw_bus_gk20a.h>
#include "nvgpu_mem.h"
/*
* MEM_ADDRESS represents arbitrary memory start address. Init function will
* allocate MEM_PAGES number of pages in memory.
*/
#define MEM_ADDRESS 0x00040000
#define MEM_PAGES 4U
#define MEM_SIZE (MEM_PAGES * SZ_4K)
/* Amount of test data should be less than or equal to MEM_SIZE */
#define TEST_SIZE (2U * SZ_4K)
#if TEST_SIZE > MEM_SIZE
#error "TEST_SIZE should be less than or equal to MEM_SIZE"
#endif
static struct nvgpu_mem *test_mem;
#ifdef CONFIG_NVGPU_DGPU
/*
* Pramin write callback (for all nvgpu_writel calls).
* No-op as callbacks/functions are already tested in pramin module.
*/
static void writel_access_reg_fn(struct gk20a *g,
struct nvgpu_reg_access *access)
{
/* No-op */
}
/*
* Pramin read callback, similar to the write callback above.
* Dummy return as callbacks/functions are already tested in pramin module.
*/
static void readl_access_reg_fn(struct gk20a *g,
struct nvgpu_reg_access *access)
{
access->value = 0;
}
/*
* Define pramin callbacks to be used during the test. Typically all
* write operations use the same callback, likewise for all read operations.
*/
static struct nvgpu_posix_io_callbacks pramin_callbacks = {
/* Write APIs all can use the same accessor. */
.writel = writel_access_reg_fn,
.writel_check = writel_access_reg_fn,
.bar1_writel = writel_access_reg_fn,
.usermode_writel = writel_access_reg_fn,
/* Likewise for the read APIs. */
.__readl = readl_access_reg_fn,
.readl = readl_access_reg_fn,
.bar1_readl = readl_access_reg_fn,
};
/*
* Populate vidmem allocations.
* These are required for testing APERTURE_VIDMEM branches.
*/
static int init_vidmem_env(struct unit_module *m, struct gk20a *g)
{
int err;
nvgpu_init_pramin(&g->mm);
nvgpu_posix_register_io(g, &pramin_callbacks);
/* Minimum HAL init for PRAMIN */
g->ops.bus.set_bar0_window = gk20a_bus_set_bar0_window;
nvgpu_pramin_ops_init(g);
unit_assert(g->ops.pramin.data032_r != NULL, return -EINVAL);
err = nvgpu_dma_alloc_vid_at(g, TEST_SIZE, test_mem, 0);
if (err != 0) {
return err;
}
return 0;
}
/* Free vidmem allocations */
static void free_vidmem_env(struct unit_module *m, struct gk20a *g)
{
nvgpu_dma_free(g, test_mem);
nvgpu_posix_io_delete_reg_space(g, bus_bar0_window_r());
}
int test_nvgpu_mem_vidmem(struct unit_module *m,
struct gk20a *g, void *args)
{
int err;
u32 memset_pattern = 0x0000005A;
u32 data_size = (16U * sizeof(u32));
u32 *data_src = (u32 *) nvgpu_kmalloc(g, data_size);
if (data_src == NULL) {
free_vidmem_env(m, g);
unit_return_fail(m, "Could not allocate data_src\n");
}
(void) memset(data_src, memset_pattern, (data_size));
/* Reset aperture to invalid, so that init doesn't complain */
test_mem->aperture = APERTURE_INVALID;
err = init_vidmem_env(m, g);
if (err != 0) {
nvgpu_kfree(g, data_src);
unit_return_fail(m, "Vidmem init failed with err=%d\n", err);
}
nvgpu_memset(g, test_mem, 0, memset_pattern, TEST_SIZE);
nvgpu_mem_wr(g, test_mem, 0, memset_pattern);
nvgpu_mem_rd(g, test_mem, 0);
nvgpu_mem_wr_n(g, test_mem, 0, data_src, data_size);
nvgpu_mem_rd_n(g, test_mem, 0, (void *)data_src, data_size);
nvgpu_kfree(g, data_src);
free_vidmem_env(m, g);
/* Reset attributes */
test_mem->aperture = APERTURE_SYSMEM;
return UNIT_SUCCESS;
}
#endif
int test_nvgpu_aperture_mask(struct unit_module *m,
struct gk20a *g, void *args)
{
u32 sysmem_mask = 1;
u32 sysmem_coh_mask = 3;
u32 vidmem_mask = 4;
u32 ret_ap_mask;
#ifdef CONFIG_NVGPU_DGPU
/* Case: APERTURE_VIDMEM */
test_mem->aperture = APERTURE_VIDMEM;
ret_ap_mask = nvgpu_aperture_mask(g, test_mem, sysmem_mask,
sysmem_coh_mask, vidmem_mask);
if (ret_ap_mask != vidmem_mask) {
unit_return_fail(m, "Vidmem mask returned incorrect\n");
}
#endif
/*
* NVGPU_MM_HONORS_APERTURE enabled
*/
nvgpu_set_enabled(g, NVGPU_MM_HONORS_APERTURE, true);
/* Case: APERTURE_SYSMEM */
test_mem->aperture = APERTURE_SYSMEM;
if (!nvgpu_aperture_is_sysmem(test_mem->aperture)) {
unit_return_fail(m, "Invalid aperture enum\n");
}
ret_ap_mask = nvgpu_aperture_mask(g, test_mem, sysmem_mask,
sysmem_coh_mask, vidmem_mask);
if (ret_ap_mask != sysmem_mask) {
unit_return_fail(m, "MM_HONORS enabled: "
"Incorrect mask returned for sysmem\n");
}
/* Case: APERTURE_SYSMEM_COH */
test_mem->aperture = APERTURE_SYSMEM_COH;
ret_ap_mask = nvgpu_aperture_mask(g, test_mem, sysmem_mask,
sysmem_coh_mask, vidmem_mask);
if (ret_ap_mask != sysmem_coh_mask) {
unit_return_fail(m, "MM_HONORS enabled: "
"Incorrect mask returned for sysmem_coh\n");
}
/* Case: APERTURE_INVALID */
test_mem->aperture = APERTURE_INVALID;
if (!EXPECT_BUG(nvgpu_aperture_mask(g, test_mem, sysmem_mask,
sysmem_coh_mask, vidmem_mask))) {
unit_return_fail(m, "MM_HONORS enabled: Aperture_mask "
"did not BUG() for APERTURE_INVALID as expected\n");
}
/* Case: Bad aperture value. This will cover default return value */
test_mem->aperture = 10;
if (!EXPECT_BUG(nvgpu_aperture_mask(g, test_mem, sysmem_mask,
sysmem_coh_mask, vidmem_mask))) {
unit_return_fail(m, "MM_HONORS enabled: Aperture_mask"
"did not BUG() for junk aperture as expected\n");
}
/*
* NVGPU_MM_HONORS_APERTURE disabled
*/
nvgpu_set_enabled(g, NVGPU_MM_HONORS_APERTURE, false);
#ifdef CONFIG_NVGPU_DGPU
/* Case: APERTURE_SYSMEM */
test_mem->aperture = APERTURE_SYSMEM;
ret_ap_mask = nvgpu_aperture_mask(g, test_mem, sysmem_mask,
sysmem_coh_mask, vidmem_mask);
if (ret_ap_mask != vidmem_mask) {
unit_return_fail(m, "MM_HONORS disabled: "
"Incorrect mask returned for sysmem\n");
}
/* Case: APERTURE_SYSMEM_COH */
test_mem->aperture = APERTURE_SYSMEM_COH;
ret_ap_mask = nvgpu_aperture_mask(g, test_mem, sysmem_mask,
sysmem_coh_mask, vidmem_mask);
if (ret_ap_mask != vidmem_mask) {
unit_return_fail(m, "MM_HONORS disabled: "
"Incorrect mask returned for sysmem_coh\n");
}
#endif
/* Case: APERTURE_INVALID */
test_mem->aperture = APERTURE_INVALID;
if (!EXPECT_BUG(nvgpu_aperture_mask(g, test_mem, sysmem_mask,
sysmem_coh_mask, vidmem_mask))) {
unit_return_fail(m, "MM_HONORS disabled: Aperture_mask "
"did not BUG() for APERTURE_INVALID as expected\n");
}
/* Case: Bad aperture value. This will cover default return value */
test_mem->aperture = 10;
if (!EXPECT_BUG(nvgpu_aperture_mask(g, test_mem, sysmem_mask,
sysmem_coh_mask, vidmem_mask))) {
unit_return_fail(m, "MM_HONORS disabled: Aperture_mask"
"did not BUG() for junk aperture as expected\n");
}
/* Reset attributes */
test_mem->aperture = APERTURE_SYSMEM;
return UNIT_SUCCESS;
}
static const char *aperture_name_str[APERTURE_MAX_ENUM + 1] = {
[APERTURE_INVALID] = "INVAL",
[APERTURE_SYSMEM] = "SYSTEM",
[APERTURE_SYSMEM_COH] = "SYSCOH",
[APERTURE_VIDMEM] = "VIDMEM",
[APERTURE_MAX_ENUM] = "UNKNOWN",
};
int test_nvgpu_aperture_str(struct unit_module *m, struct gk20a *g, void *args)
{
enum nvgpu_aperture ap = 0;
const char *name_str;
while (ap <= APERTURE_MAX_ENUM) {
name_str = nvgpu_aperture_str(ap);
if (strcmp((name_str), aperture_name_str[ap]) != 0) {
unit_return_fail(m,
"Incorrect aperture str for aperture %d\n", ap);
}
ap += 1;
}
return UNIT_SUCCESS;
}
int test_nvgpu_mem_iommu_translate(struct unit_module *m,
struct gk20a *g, void *args)
{
u64 temp_phys;
struct nvgpu_mem_sgl *test_sgl =
(struct nvgpu_mem_sgl *) test_mem->phys_sgt->sgl;
struct nvgpu_os_posix *p = nvgpu_os_posix_from_gk20a(g);
/*
* Case: mm is not iommuable
* This is specified in nvgpu_os_posix structure.
*/
temp_phys = nvgpu_mem_iommu_translate(g, test_sgl->phys);
if (temp_phys != test_sgl->phys) {
unit_return_fail(m, "iommu_translate did not return "
"same phys as expected\n");
}
/*
* Case: mm is not iommuable
* But, mm_is_iommuable = true.
*/
p->mm_is_iommuable = true;
g->ops.mm.gmmu.get_iommu_bit = NULL;
temp_phys = nvgpu_mem_iommu_translate(g, test_sgl->phys);
if (temp_phys != test_sgl->phys) {
unit_return_fail(m, "iommu_translate: mm_is_iommuable=true: "
"did not return same phys as expected\n");
}
/*
* Case: mm is iommuable
* Set HAL to enable iommu_translate
*/
g->ops.mm.gmmu.get_iommu_bit = gp10b_mm_get_iommu_bit;
temp_phys = nvgpu_mem_iommu_translate(g, test_sgl->phys);
if (temp_phys == test_sgl->phys) {
unit_return_fail(m,
"iommu_translate did not translate address\n");
}
/* Reset iommuable settings */
p->mm_is_iommuable = false;
return UNIT_SUCCESS;
}
int test_nvgpu_memset_sysmem(struct unit_module *m,
struct gk20a *g, void *args)
{
u32 i;
u32 memset_pattern = 0x0000005A;
u32 memset_pattern_word =
(memset_pattern << 24) | (memset_pattern << 16) |
(memset_pattern << 8) | (memset_pattern);
u32 memset_words = TEST_SIZE / sizeof(u32);
u32 *test_cpu_va = (u32 *)test_mem->cpu_va;
/* Case: APERTURE_SYSMEM */
test_mem->aperture = APERTURE_SYSMEM;
nvgpu_memset(g, test_mem, 0, memset_pattern, TEST_SIZE);
for (i = 0; i < memset_words; i++) {
if (test_cpu_va[i] != memset_pattern_word) {
unit_return_fail(m,
"Memset pattern not found at offset %d\n", i);
}
}
/* Case: APERTURE_INVALID */
test_mem->aperture = APERTURE_INVALID;
if (!EXPECT_BUG(nvgpu_memset(g, test_mem, 0,
memset_pattern, TEST_SIZE))) {
unit_return_fail(m, "APERTURE_INVALID: "
"nvgpu_memset did not BUG() as expected\n");
}
/* Reset attributes */
test_mem->aperture = APERTURE_SYSMEM;
return UNIT_SUCCESS;
}
int test_nvgpu_mem_wr_rd(struct unit_module *m,
struct gk20a *g, void *args)
{
u32 i;
u32 data_rd, data_words = 16U;
u32 test_offset = 0x400;
u32 data_pattern = 0x5A5A5A5A;
u32 *test_cpu_va = (u32 *)test_mem->cpu_va;
u32 data_size = (data_words * sizeof(u32));
u32 *data_src, *data_rd_buf;
u64 data_rd_pair;
/* Test nvgpu_mem_is_sysmem()*/
/* Case: APERTURE_INVALID */
test_mem->aperture = APERTURE_INVALID;
if (nvgpu_mem_is_sysmem(test_mem) != false) {
unit_return_fail(m, "nvgpu_mem_is_sysmem "
"returns true for APERTURE_INVALID\n");
}
if (nvgpu_mem_is_valid(test_mem) != false) {
unit_return_fail(m, "nvgpu_mem_is_valid "
"returns true for APERTURE_INVALID\n");
}
/* Case: APERTURE_SYSMEM_COH */
test_mem->aperture = APERTURE_SYSMEM_COH;
/* Confirm nvgpu_mem is set to SYSMEM*/
if (nvgpu_mem_is_sysmem(test_mem) != true) {
unit_return_fail(m, "nvgpu_mem_is_sysmem "
"returns false for APERTURE_SYSMEM_COH\n");
}
/* Case: APERTURE_SYSMEM */
test_mem->aperture = APERTURE_SYSMEM;
if (nvgpu_mem_is_sysmem(test_mem) != true) {
unit_return_fail(m, "nvgpu_mem_is_sysmem "
"returns false for APERTURE_SYSMEM\n");
}
/* Confirm nvgpu_mem is allocated*/
if (nvgpu_mem_is_valid(test_mem) != true) {
unit_return_fail(m, "nvgpu_mem_is_valid "
"returns false for APERTURE_SYSMEM\n");
}
/* Test read and write functions */
/* Case: APERTURE_SYSMEM */
nvgpu_mem_wr(g, test_mem, test_offset, data_pattern);
if (test_cpu_va[(test_offset / (u32)sizeof(u32))] != data_pattern) {
unit_err(m,
"mem_wr incorrect write at offset %d\n", test_offset);
goto return_fail;
}
data_rd = nvgpu_mem_rd(g, test_mem, test_offset);
if (data_rd != data_pattern) {
unit_err(m,
"mem_rd data at offset %d incorrect\n", test_offset);
goto return_fail;
}
data_src = (u32 *) nvgpu_kmalloc(g, data_size);
if (data_src == NULL) {
unit_err(m, "Could not allocate data_src\n");
goto return_fail;
}
(void) memset(data_src, data_pattern, (data_size));
nvgpu_mem_wr_n(g, test_mem, 0, data_src, data_size);
for (i = 0; i < data_words; i++) {
if (test_cpu_va[i] != data_src[i]) {
unit_err(m,
"mem_wr_n incorrect write at offset %d\n", i);
goto free_data_src;
}
}
data_rd_buf = (u32 *) nvgpu_kzalloc(g, data_size);
if (data_rd_buf == NULL) {
unit_err(m, "Could not allocate data_rd_buf\n");
goto free_data_src;
}
nvgpu_mem_rd_n(g, test_mem, 0, (void *)data_rd_buf, data_size);
for (i = 0; i < data_words; i++) {
if (data_rd_buf[i] != data_src[i]) {
unit_err(m,
"mem_rd_n data at offset %d incorrect\n", i);
goto free_buffers;
}
}
data_rd_pair = nvgpu_mem_rd32_pair(g, test_mem, 0, 1);
if (data_rd_pair != ((u64)data_pattern |
((u64)data_pattern << 32ULL))) {
unit_err(m, "nvgpu_mem_rd32_pair pattern incorrect\n");
goto free_buffers;
}
/* Case: APERTURE_INVALID */
test_mem->aperture = APERTURE_INVALID;
if (!EXPECT_BUG(nvgpu_mem_wr(g, test_mem, test_offset, data_pattern))) {
unit_err(m,
"APERTURE_INVALID: mem_wr did not BUG() as expected\n");
goto free_buffers;
}
if (!EXPECT_BUG(nvgpu_mem_rd(g, test_mem, test_offset))) {
unit_err(m, "APERTURE_INVALID: "
"mem_rd did not BUG() as expected\n");
goto free_buffers;
}
if (!EXPECT_BUG(nvgpu_mem_wr_n(g, test_mem, 0, data_src, data_size))) {
unit_err(m, "APERTURE_INVALID: "
"mem_wr_n did not BUG() as expected\n");
goto free_buffers;
}
if (!EXPECT_BUG(nvgpu_mem_rd_n(g, test_mem, 0,
(void *)data_rd_buf, data_size))) {
unit_err(m, "APERTURE_INVALID: "
"mem_rd_n did not BUG() as expected\n");
goto free_buffers;
}
nvgpu_kfree(g, data_src);
data_src = NULL;
nvgpu_kfree(g, data_rd_buf);
data_rd_buf = NULL;
/* Reset attribute */
test_mem->aperture = APERTURE_SYSMEM;
return UNIT_SUCCESS;
free_buffers:
nvgpu_kfree(g, data_rd_buf);
free_data_src:
nvgpu_kfree(g, data_src);
return_fail:
return UNIT_FAIL;
}
/*
* Test: test_nvgpu_mem_phys_ops
*/
int test_nvgpu_mem_phys_ops(struct unit_module *m,
struct gk20a *g, void *args)
{
u64 ret;
struct nvgpu_gmmu_attrs *attrs = NULL;
struct nvgpu_sgt *test_sgt = test_mem->phys_sgt;
void *test_sgl = test_sgt->sgl;
void *temp_sgl = test_sgt->ops->sgl_next(test_sgl);
if (temp_sgl != NULL) {
unit_return_fail(m,
"nvgpu_mem_phys_sgl_next not NULL as expected\n");
}
ret = test_sgt->ops->sgl_dma(test_sgl);
if (ret != MEM_ADDRESS) {
unit_return_fail(m,
"nvgpu_mem_phys_sgl_dma not equal to phys as expected\n");
}
ret = test_sgt->ops->sgl_phys(g, test_sgl);
if (ret != MEM_ADDRESS) {
unit_return_fail(m,
"nvgpu_mem_phys_sgl_phys not equal to phys as expected\n");
}
ret = test_sgt->ops->sgl_ipa(g, test_sgl);
if (ret != MEM_ADDRESS) {
unit_return_fail(m, "nvgpu_mem_phys_sgl_ipa incorrect\n");
}
ret = test_sgt->ops->sgl_ipa_to_pa(g, test_sgl, 0ULL, NULL);
if (ret != 0ULL) {
unit_return_fail(m,
"nvgpu_mem_phys_sgl_ipa_to_pa not zero as expected\n");
}
ret = test_sgt->ops->sgl_length(test_sgl);
if (ret != MEM_SIZE) {
unit_return_fail(m, "nvgpu_mem_phys_sgl_length incorrect\n");
}
ret = test_sgt->ops->sgl_gpu_addr(g, test_sgl, attrs);
if (ret != MEM_ADDRESS) {
unit_return_fail(m, "nvgpu_mem_phys_sgl_gpu_addr incorrect\n");
}
if (test_sgt->ops->sgt_iommuable != NULL) {
unit_return_fail(m, "physical nvgpu_mems is not IOMMU'able\n");
}
/*
* Test nvgpu_mem_phys_sgt_free - No-op
*/
test_sgt->ops->sgt_free(g, test_sgt);
return UNIT_SUCCESS;
}
int test_nvgpu_mem_create_from_phys(struct unit_module *m,
struct gk20a *g, void *args)
{
int err;
struct nvgpu_posix_fault_inj *kmem_fi =
nvgpu_kmem_get_fault_injection();
test_mem = (struct nvgpu_mem *)
nvgpu_kzalloc(g, sizeof(struct nvgpu_mem));
if (test_mem == NULL) {
unit_return_fail(m, "Couldn't allocate memory for nvgpu_mem\n");
}
/*
* Test 1 - Enable SW fault injection and check that init function
* fails with -ENOMEM.
*/
nvgpu_posix_enable_fault_injection(kmem_fi, true, 0);
err = nvgpu_mem_create_from_phys(g, test_mem, MEM_ADDRESS, MEM_PAGES);
if (err != -ENOMEM) {
unit_return_fail(m,
"nvgpu_mem_create_from_phys didn't fail as expected\n");
}
nvgpu_posix_enable_fault_injection(kmem_fi, false, 0);
/*
* Test 2 - Enable SW fault injection for second allocation and
* check that init function fails with -ENOMEM.
*/
nvgpu_posix_enable_fault_injection(kmem_fi, true, 1);
err = nvgpu_mem_create_from_phys(g, test_mem, MEM_ADDRESS, MEM_PAGES);
if (err != -ENOMEM) {
unit_return_fail(m,
"nvgpu_mem_create_from_phys didn't fail as expected\n");
}
nvgpu_posix_enable_fault_injection(kmem_fi, false, 0);
/*
* Test 3 - Check that physical memory is inited successfully
* Use this allocated memory for next tests in module.
*/
err = nvgpu_mem_create_from_phys(g, test_mem, MEM_ADDRESS, MEM_PAGES);
if (err != 0) {
unit_return_fail(m, "nvgpu_mem_create_from_phys init failed\n");
}
if (nvgpu_mem_get_phys_addr(g, test_mem) != ((u64) test_mem->cpu_va)) {
unit_return_fail(m, "invalid physical address\n");
}
if (nvgpu_mem_get_addr(g, test_mem) != ((u64) test_mem->cpu_va)) {
unit_return_fail(m, "invalid nvgpu_mem_get_addr address\n");
}
/* Allocate cpu_va for later tests */
test_mem->cpu_va = nvgpu_kzalloc(g, MEM_SIZE);
if (test_mem->cpu_va == NULL) {
nvgpu_kfree(g, test_mem);
unit_return_fail(m, "Could not allocate memory for cpu_va\n");
}
return UNIT_SUCCESS;
}
int test_nvgpu_mem_create_from_mem(struct unit_module *m, struct gk20a *g,
void *args)
{
struct nvgpu_mem dest_mem;
nvgpu_mem_create_from_mem(g, &dest_mem, test_mem, 0, 2);
unit_assert(dest_mem.cpu_va == test_mem->cpu_va, goto done);
unit_assert(dest_mem.size == (2 * NVGPU_CPU_PAGE_SIZE), goto done);
unit_assert((dest_mem.mem_flags & NVGPU_MEM_FLAG_SHADOW_COPY) == true,
goto done);
unit_assert(dest_mem.aperture == APERTURE_SYSMEM, goto done);
return UNIT_SUCCESS;
done:
unit_return_fail(m, "%s: failed!\n", __func__);
}
int test_free_nvgpu_mem(struct unit_module *m, struct gk20a *g, void *args)
{
test_mem->aperture = APERTURE_SYSMEM;
nvgpu_dma_free(g, test_mem);
nvgpu_kfree(g, test_mem);
return UNIT_SUCCESS;
}
struct unit_module_test nvgpu_mem_tests[] = {
/*
* Init test should run first in order to use allocated memory.
*/
UNIT_TEST(mem_create_from_phys, test_nvgpu_mem_create_from_phys, NULL, 0),
/*
* Tests for SYSMEM
*/
UNIT_TEST(nvgpu_mem_phys_ops, test_nvgpu_mem_phys_ops, NULL, 2),
UNIT_TEST(nvgpu_memset_sysmem, test_nvgpu_memset_sysmem, NULL, 0),
UNIT_TEST(nvgpu_mem_wr_rd, test_nvgpu_mem_wr_rd, NULL, 0),
UNIT_TEST(mem_iommu_translate, test_nvgpu_mem_iommu_translate, NULL, 2),
/*
* Tests covering VIDMEM branches
*/
UNIT_TEST(nvgpu_aperture_mask, test_nvgpu_aperture_mask, NULL, 0),
UNIT_TEST(nvgpu_aperture_name, test_nvgpu_aperture_str, NULL, 0),
UNIT_TEST(create_mem_from_mem, test_nvgpu_mem_create_from_mem, NULL, 0),
#ifdef CONFIG_NVGPU_DGPU
UNIT_TEST(nvgpu_mem_vidmem, test_nvgpu_mem_vidmem, NULL, 2),
#endif
/*
* Free test should be executed at the end to free allocated memory.
* As nvgpu_mem doesn't not have an explicit free function for sysmem,
* this test doesn't cover any nvgpu_mem code.
*/
UNIT_TEST(test_free_nvgpu_mem, test_free_nvgpu_mem, NULL, 0),
};
UNIT_MODULE(nvgpu_mem, nvgpu_mem_tests, UNIT_PRIO_NVGPU_TEST);

View File

@@ -0,0 +1,267 @@
/*
* Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef UNIT_NVGPU_MEM_H
#define UNIT_NVGPU_MEM_H
struct gk20a;
struct unit_module;
/** @addtogroup SWUTS-mm-nvgpu-mem
* @{
*
* Software Unit Test Specification for mm.nvgpu_mem
*/
/**
* Test specification for: test_nvgpu_mem_create_from_phys
*
* Description: Initialize nvgpu_mem for given size and base address.
*
* Test Type: Feature, Error injection
*
* Targets: nvgpu_mem_create_from_phys
*
* Targets: nvgpu_mem_create_from_phys, nvgpu_mem_get_phys_addr,
* nvgpu_mem_get_addr
*
* Input: None
*
* Steps:
* - Initialize nvgpu_mem
* - Allocate memory for nvgpu_mem sgt and sgl
* - Initialize nvgpu_mem structure members to appropriate value.
* - Allocate cpu_va memory for later tests
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_nvgpu_mem_create_from_phys(struct unit_module *m,
struct gk20a *g, void *args);
/**
* Test specification for: test_nvgpu_mem_phys_ops
*
* Description: Check all nvgpu_sgt_ops functions
*
* Test Type: Feature
*
* Targets: nvgpu_mem.nvgpu_sgt.nvgpu_sgt_ops.sgl_next,
* nvgpu_mem.nvgpu_sgt.nvgpu_sgt_ops.sgl_dma,
* nvgpu_mem.nvgpu_sgt.nvgpu_sgt_ops.sgl_phys,
* nvgpu_mem.nvgpu_sgt.nvgpu_sgt_ops.sgl_ipa,
* nvgpu_mem.nvgpu_sgt.nvgpu_sgt_ops.sgl_ipa_to_pa,
* nvgpu_mem.nvgpu_sgt.nvgpu_sgt_ops.sgl_length,
* nvgpu_mem.nvgpu_sgt.nvgpu_sgt_ops.sgl_gpu_addr,
* nvgpu_mem.nvgpu_sgt.nvgpu_sgt_ops.sgt_free
*
* Input: test_nvgpu_mem_create_from_phys
*
* Steps:
* - Execute nvgpu_sgt_ops functions
* - Check if each nvgpu_sgt_ops function executes and returns expected value.
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_nvgpu_mem_phys_ops(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_nvgpu_memset_sysmem
*
* Description: Store pre-defined pattern at allocated nvgpu_mem address
*
* Test Type: Feature
*
* Targets: nvgpu_memset
*
* Input: test_nvgpu_mem_create_from_phys
*
* Steps:
* - Store data pattern and check value for multiple cases
* - Execute below steps for APERTURE_SYSMEM and APERTURE_INVALID cases
* - Using nvgpu_memset() store pre-defined data pattern in part of allocated
* memory
* - Check if set data pattern is correctly stored
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_nvgpu_memset_sysmem(struct unit_module *m,
struct gk20a *g, void *args);
/**
* Test specification for: test_nvgpu_mem_wr_rd
*
* Description: Test read and write functions for sysmem
*
* Test Type: Feature
*
* Targets: nvgpu_mem_is_sysmem, nvgpu_mem_is_valid, nvgpu_mem_wr, nvgpu_mem_rd,
* nvgpu_mem_wr_n, nvgpu_mem_rd_n, nvgpu_mem_rd32_pair, nvgpu_mem_rd32,
* nvgpu_mem_wr32
*
* Input: test_nvgpu_mem_create_from_phys
*
* Steps:
* - Check if memory is of sysmem type
* - Check if memory aperture is not invalid
* - Execute below steps for APERTURE_SYSMEM and APERTURE_INVALID cases
* - Execute all write functions and confirm data written
* - Write preset data pattern to allocated nvgpu_mem
* - Confirm data written at the memory location is correct
* - Execute read functions and confirm data read
* - Read data from a segment of allocated memory
* - Confirm read data is correct
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_nvgpu_mem_wr_rd(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_nvgpu_mem_iommu_translate
*
* Description: Test if given address is iommuable
*
* Test Type: Feature
*
* Targets: nvgpu_mem_iommu_translate
*
* Input: test_nvgpu_mem_create_from_phys
*
* Steps:
* - Check if nvgpu_mem is iommuable
* - Return value is equal to nvgpu_mem phys address value
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_nvgpu_mem_iommu_translate(struct unit_module *m,
struct gk20a *g, void *args);
/**
* Test specification for: test_nvgpu_aperture_mask
*
* Description: Check if nvgpu_mem aperture is correct
*
* Test Type: Feature
*
* Targets: nvgpu_aperture_mask, nvgpu_aperture_mask_raw,
* nvgpu_aperture_is_sysmem
*
* Input: test_nvgpu_mem_create_from_phys
*
* Steps:
* - Execute these steps for all the aperture types
* - Check if nvgpu_mem aperture mask values returned are as expected
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_nvgpu_aperture_mask(struct unit_module *m,
struct gk20a *g, void *args);
/**
* Test specification for: test_nvgpu_aperture_str
*
* Description: Check nvgpu_mem aperture name string
*
* Test Type: Feature
*
* Targets: nvgpu_aperture_str
*
* Input: test_nvgpu_mem_create_from_phys
*
* Steps:
* - Run nvgpu_aperture_str function for all aperture values.
* - Confirm that returned aperture name is correct as per input aperture.
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_nvgpu_aperture_str(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_nvgpu_mem_create_from_mem
*
* Description: Create nvgpu_mem from another nvgpu_mem struct
*
* Test Type: Feature
*
* Targets: nvgpu_mem_create_from_mem
*
* Input: test_nvgpu_mem_create_from_phys
*
* Steps:
* - Create a nvgpu_mem structure with 2 pages from global nvgpu_mem struct.
* - Confirm that returned destination nvgpu_mem address and size corresponds to
* - 2 pages of global nvgpu_mem structure with SYSMEM aperture.
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_nvgpu_mem_create_from_mem(struct unit_module *m, struct gk20a *g,
void *args);
/**
* Test specification for: test_nvgpu_mem_vidmem
*
* Description: Test read and write memory functions for vidmem
*
* Test Type: Feature
*
* Targets: nvgpu_mem_is_sysmem, nvgpu_mem_is_valid, nvgpu_mem_wr, nvgpu_mem_rd,
* nvgpu_mem_wr_n, nvgpu_mem_rd_n, nvgpu_mem_rd32_pair, nvgpu_mem_rd32,
* nvgpu_mem_wr32
*
* Input: test_nvgpu_mem_create_from_phys
*
* Steps:
* - Execute read and write calls for vidmem which are converted to pramin calls
* - pramin functions are tested in pramin module
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_nvgpu_mem_vidmem(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_free_nvgpu_mem
*
* Description: Cleanup allocated memory for nvgpu_mem structure
*
* Test Type: Other (cleanup)
*
* Targets: None
*
* Input: test_nvgpu_mem_create_from_phys
*
* Steps:
* - Free allocated memory
*
* Output: Returns SUCCESS if the steps above were executed successfully. FAIL
* otherwise.
*/
int test_free_nvgpu_mem(struct unit_module *m, struct gk20a *g, void *args);
#endif /* UNIT_NVGPU_MEM_H */