gpu: nvgpu: unit: allocator unit test

This unit test covers the nvgpu allocator high level logic for
calling nvgpu allocator imlementation routines. The nvgpu_allocator
code is generally very simple.

This gets to >90% coverage of the module. Once the fault injection
code is merged the failure path after nvgpu_mutex_init() will also
be coverable.

JIRA NVGPU-903

Change-Id: I7e180da9cbc518b6568c240fd5e67a233b17edc6
Signed-off-by: Alex Waterman <alexw@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1927642
Reviewed-by: Philip Elcan <pelcan@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Alex Waterman
2018-10-12 10:09:40 -07:00
committed by mobile promotions
parent 4453788314
commit f96d229e70
7 changed files with 434 additions and 15 deletions

View File

@@ -27,6 +27,7 @@ NV_REPOSITORY_COMPONENTS += userspace/units/posix-env
NV_REPOSITORY_COMPONENTS += userspace/units/posix-mockio
NV_REPOSITORY_COMPONENTS += userspace/units/posix-fault-injection
NV_REPOSITORY_COMPONENTS += userspace/units/nvgpu-pramin
NV_REPOSITORY_COMPONENTS += userspace/units/mm/nvgpu_allocator
endif
# Local Variables:

View File

@@ -1,5 +1,12 @@
# Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
__bug
__nvgpu_kfree
__nvgpu_kmalloc
__nvgpu_posix_ffs
__nvgpu_posix_fls
__nvgpu_readl
__nvgpu_set_enabled
bitmap_clear
bitmap_find_next_zero_area_off
bitmap_set
@@ -8,12 +15,32 @@ find_first_bit
find_first_zero_bit
find_next_bit
gk20a_bus_set_bar0_window
nvgpu_alloc
nvgpu_alloc_base
nvgpu_alloc_common_init
nvgpu_alloc_destroy
nvgpu_alloc_end
nvgpu_alloc_fixed
nvgpu_alloc_initialized
nvgpu_alloc_length
nvgpu_alloc_pte
nvgpu_alloc_release_carveout
nvgpu_alloc_reserve_carveout
nvgpu_alloc_space
nvgpu_bar1_readl
nvgpu_bar1_writel
nvgpu_free
nvgpu_free_enabled_flags
nvgpu_free_fixed
nvgpu_init_enabled_flags
nvgpu_init_pramin
nvgpu_kmem_cache_alloc
nvgpu_kmem_cache_create
nvgpu_kmem_cache_destroy
nvgpu_kmem_cache_free
nvgpu_kmem_get_fault_injection
nvgpu_posix_cleanup
nvgpu_posix_enable_fault_injection
nvgpu_posix_io_add_reg_space
nvgpu_posix_io_check_sequence
nvgpu_posix_io_delete_reg_space
@@ -23,6 +50,7 @@ nvgpu_posix_io_readl_reg_space
nvgpu_posix_io_record_access
nvgpu_posix_io_start_recorder
nvgpu_posix_io_writel_reg_space
nvgpu_posix_is_fault_injection_triggered
nvgpu_posix_probe
nvgpu_posix_register_io
nvgpu_pramin_memset
@@ -37,17 +65,3 @@ set_bit
test_and_clear_bit
test_and_set_bit
test_bit
__bug
__nvgpu_posix_ffs
__nvgpu_posix_fls
__nvgpu_readl
__nvgpu_set_enabled
nvgpu_posix_enable_fault_injection
nvgpu_posix_is_fault_injection_triggered
__nvgpu_kmalloc
__nvgpu_kfree
nvgpu_kmem_cache_create
nvgpu_kmem_cache_destroy
nvgpu_kmem_cache_alloc
nvgpu_kmem_cache_free
nvgpu_kmem_get_fault_injection

View File

@@ -51,7 +51,8 @@ UNITS := \
$(UNIT_SRC)/posix-bitops \
$(UNIT_SRC)/posix-mockio \
$(UNIT_SRC)/posix-fault-injection \
$(UNIT_SRC)/nvgpu-pramin
$(UNIT_SRC)/nvgpu-pramin \
$(UNIT_SRC)/mm/nvgpu_allocator
# A test unit. Not really needed any more...
# $(UNIT_SRC)/test

View File

@@ -0,0 +1,26 @@
# Copyright (c) 2018, 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_allocator.o
MODULE = nvgpu_allocator
include ../../Makefile.units

View File

@@ -0,0 +1,23 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# Copyright (c) 2018, NVIDIA CORPORATION. All Rights Reserved.
#
# NVIDIA CORPORATION and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto. Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA CORPORATION is strictly prohibited.
#
# tmake for SW Mobile component makefile
#
###############################################################################
NVGPU_UNIT_NAME=nvgpu_allocator
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,23 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# Copyright (c) 2018 NVIDIA CORPORATION. All Rights Reserved.
#
# NVIDIA CORPORATION and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto. Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA CORPORATION is strictly prohibited.
#
# tmake for SW Mobile component makefile
#
###############################################################################
NVGPU_UNIT_NAME=nvgpu_allocator
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,331 @@
/*
* Copyright (c) 2018, 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 <unit/io.h>
#include <unit/unit.h>
#include <nvgpu/types.h>
#include <nvgpu/allocator.h>
#define OP_ALLOC 0
#define OP_FREE 1
#define OP_ALLOC_PTE 2
#define OP_ALLOC_FIXED 3
#define OP_FREE_FIXED 4
#define OP_RESERVE_CARVEOUT 5
#define OP_RELEASE_CARVEOUT 6
#define OP_BASE 7
#define OP_LENGTH 8
#define OP_END 9
#define OP_INITED 10
#define OP_SPACE 11
#define OP_NUMBER 12
static bool dummy_op_called[OP_NUMBER];
static const char *ops_str[] = {
"alloc",
"free",
"alloc_pte",
"alloc_fixed",
"free fixed",
"reserve_carveout",
"release_carveout",
"base",
"length",
"end",
"inited",
"space",
};
static u64 dummy_alloc(struct nvgpu_allocator *allocator, u64 len)
{
dummy_op_called[OP_ALLOC] = true;
return 0ULL;
}
static void dummy_free(struct nvgpu_allocator *allocator, u64 addr)
{
dummy_op_called[OP_FREE] = true;
}
static u64 dummy_alloc_pte(struct nvgpu_allocator *allocator, u64 len,
u32 page_size)
{
dummy_op_called[OP_ALLOC_PTE] = true;
return 0ULL;
}
static u64 dummy_alloc_fixed(struct nvgpu_allocator *allocator,
u64 base, u64 len, u32 page_size)
{
dummy_op_called[OP_ALLOC_FIXED] = true;
return 0ULL;
}
static void dummy_free_fixed(struct nvgpu_allocator *allocator,
u64 base, u64 len)
{
dummy_op_called[OP_FREE_FIXED] = true;
}
static int dummy_reserve_carveout(struct nvgpu_allocator *allocator,
struct nvgpu_alloc_carveout *co)
{
dummy_op_called[OP_RESERVE_CARVEOUT] = true;
return 0;
}
static void dummy_release_carveout(struct nvgpu_allocator *allocator,
struct nvgpu_alloc_carveout *co)
{
dummy_op_called[OP_RELEASE_CARVEOUT] = true;
}
static u64 dummy_base(struct nvgpu_allocator *allocator)
{
dummy_op_called[OP_BASE] = true;
return 0ULL;
}
static u64 dummy_length(struct nvgpu_allocator *allocator)
{
dummy_op_called[OP_LENGTH] = true;
return 0ULL;
}
static u64 dummy_end(struct nvgpu_allocator *allocator)
{
dummy_op_called[OP_END] = true;
return 0ULL;
}
static bool dummy_inited(struct nvgpu_allocator *allocator)
{
dummy_op_called[OP_INITED] = true;
return false;
}
static u64 dummy_space(struct nvgpu_allocator *allocator)
{
dummy_op_called[OP_SPACE] = true;
return false;
}
static void dummy_fini(struct nvgpu_allocator *allocator)
{
}
static struct nvgpu_allocator_ops dummy_ops = {
.alloc = dummy_alloc,
.free = dummy_free,
.alloc_pte = dummy_alloc_pte,
.alloc_fixed = dummy_alloc_fixed,
.free_fixed = dummy_free_fixed,
.reserve_carveout = dummy_reserve_carveout,
.release_carveout = dummy_release_carveout,
.base = dummy_base,
.length = dummy_length,
.end = dummy_end,
.inited = dummy_inited,
.space = dummy_space,
.fini = dummy_fini
};
/*
* Make sure the op functions are called and that's it. Verifying that the ops
* actually do what they are supposed to do is the responsibility of the unit
* tests for the actual allocator implementations.
*
* In this unit test the meaning of these ops can't really be assumed. But we
* can test that the logic for only calling present ops is tested.
*
* Also note: we don't test the fini op here; instead we test it separately as
* part of the init/destroy functionality.
*/
static int test_nvgpu_alloc_ops_present(struct unit_module *m,
struct gk20a *g, void *args)
{
u32 i;
int err;
bool failed;
struct nvgpu_allocator a;
memset(dummy_op_called, 0, sizeof(dummy_op_called));
err = nvgpu_alloc_common_init(&a, NULL, "test",
NULL, false, &dummy_ops);
if (err)
unit_return_fail(m, "Unexpected common_init() fail!\n");
/*
* Now that we have the allocator just call all the alloc functions and
* make sure that the associated bool is true.
*/
nvgpu_alloc(&a, 0UL);
nvgpu_alloc_pte(&a, 0UL, 0U);
nvgpu_alloc_fixed(&a, 0UL, 0UL, 0U);
nvgpu_free(&a, 0UL);
nvgpu_free_fixed(&a, 0UL, 0UL);
nvgpu_alloc_reserve_carveout(&a, NULL);
nvgpu_alloc_release_carveout(&a, NULL);
nvgpu_alloc_base(&a);
nvgpu_alloc_length(&a);
nvgpu_alloc_end(&a);
nvgpu_alloc_initialized(&a);
nvgpu_alloc_space(&a);
failed = false;
for (i = 0; i < OP_NUMBER; i++) {
if (!dummy_op_called[i]) {
failed = true;
unit_info(m, "%s did not call op function!\n",
ops_str[i]);
}
}
if (failed)
unit_return_fail(m, "OPs uncalled!\n");
/*
* Next make sure that if the ops are NULL we don't crash or anything
* like that.
*
* Note that not all ops have if NULL checks. We skip these in the unit
* test.
*/
memset(dummy_op_called, 0, sizeof(dummy_op_called));
memset(&dummy_ops, 0, sizeof(dummy_ops));
nvgpu_alloc_fixed(&a, 0UL, 0UL, 0U);
nvgpu_free_fixed(&a, 0UL, 0UL);
nvgpu_alloc_reserve_carveout(&a, NULL);
nvgpu_alloc_release_carveout(&a, NULL);
nvgpu_alloc_base(&a);
nvgpu_alloc_length(&a);
nvgpu_alloc_end(&a);
nvgpu_alloc_initialized(&a);
nvgpu_alloc_space(&a);
failed = false;
for (i = 0; i < OP_NUMBER; i++) {
if (dummy_op_called[i]) {
failed = true;
unit_info(m, "op function %s called despite null op!\n",
ops_str[i]);
}
}
if (failed)
unit_return_fail(m, "OPs called!\n");
return UNIT_SUCCESS;
}
/*
* Test the common_init() function used by all allocator implementations. The
* test here is to simply catch that the various invalid input checks are
* exercised and that the parameters passed into the common_init() make their
* way into the allocator struct.
*/
static int test_nvgpu_alloc_common_init(struct unit_module *m,
struct gk20a *g, void *args)
{
struct nvgpu_allocator a;
struct nvgpu_allocator_ops ops = { };
void *dummy_priv = (void *)0x10000;
void *dummy_g = (void *)0x1000;
if (nvgpu_alloc_common_init(NULL, NULL, NULL, NULL, false, NULL) == 0)
unit_return_fail(m, "Made NULL allocator!?\n");
/*
* Hit all the invalid ops struct criteria.
*/
if (nvgpu_alloc_common_init(&a, NULL, "test", NULL, false, &ops) == 0)
unit_return_fail(m, "common_init passes despite empty ops\n");
ops.alloc = dummy_alloc;
if (nvgpu_alloc_common_init(&a, NULL, "test", NULL, false, &ops) == 0)
unit_return_fail(m,
"common_init passes despite missing free(),fini()\n");
ops.free = dummy_free;
if (nvgpu_alloc_common_init(&a, NULL, "test", NULL, false, &ops) == 0)
unit_return_fail(m,
"common_init passes despite missing fini()\n");
ops.fini = dummy_fini;
if (0 != nvgpu_alloc_common_init(&a, dummy_g, "test",
dummy_priv, true, &ops))
unit_return_fail(m, "common_init should have passed\n");
/*
* Verify that the allocator struct actually is made correctly.
*/
if (a.g != dummy_g || a.priv != dummy_priv ||
a.debug != true || a.ops != &ops)
unit_return_fail(m, "Invalid data in allocator\n");
if (strcmp(a.name, "test") != 0)
unit_return_fail(m, "Invalid name in allocator\n");
return UNIT_SUCCESS;
}
/*
* Test that the destroy function works. This just calls the fini() op and
* expects the allocator to have been completely zeroed.
*/
static int test_nvgpu_alloc_destroy(struct unit_module *m,
struct gk20a *g, void *args)
{
struct nvgpu_allocator a;
struct nvgpu_allocator zero_a = { };
struct nvgpu_allocator_ops ops = {
.alloc = dummy_alloc,
.free = dummy_free,
.fini = dummy_fini,
};
if (nvgpu_alloc_common_init(&a, NULL, "test", NULL, false, &ops) != 0)
unit_return_fail(m, "common_init failed with valid input\n");
nvgpu_alloc_destroy(&a);
if (memcmp(&a, &zero_a, sizeof(a)) != 0)
unit_return_fail(m, "Allocator has not been memset to 0\n");
return UNIT_SUCCESS;
}
struct unit_module_test nvgpu_allocator_tests[] = {
UNIT_TEST(common_init, test_nvgpu_alloc_common_init, NULL),
UNIT_TEST(alloc_destroy, test_nvgpu_alloc_destroy, NULL),
UNIT_TEST(alloc_ops, test_nvgpu_alloc_ops_present, NULL),
};
UNIT_MODULE(nvgpu_allocator, nvgpu_allocator_tests, UNIT_PRIO_NVGPU_TEST);