mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-23 09:57:08 +03:00
gpu: nvgpu: unit: add tests for common.mm.vm_area
Expand testing within commom.mm.vm to include vm_area as well since those 2 units are very closely related. JIRA NVGPU-909 Change-Id: Id9721bcf4bfdaf7f1a2711859ab2ac524c81e004 Signed-off-by: Nicolas Benech <nbenech@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/2231656 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
committed by
Alex Waterman
parent
767e505792
commit
cb2170d3c8
@@ -401,6 +401,7 @@ nvgpu_vfree_impl
|
|||||||
nvgpu_vm_alloc_va
|
nvgpu_vm_alloc_va
|
||||||
nvgpu_vm_area_alloc
|
nvgpu_vm_area_alloc
|
||||||
nvgpu_vm_area_free
|
nvgpu_vm_area_free
|
||||||
|
nvgpu_vm_area_validate_buffer
|
||||||
nvgpu_vm_bind_channel
|
nvgpu_vm_bind_channel
|
||||||
nvgpu_vm_do_init
|
nvgpu_vm_do_init
|
||||||
nvgpu_vm_find_mapped_buf
|
nvgpu_vm_find_mapped_buf
|
||||||
|
|||||||
@@ -55,11 +55,11 @@
|
|||||||
/* Check if address is aligned at the requested boundary */
|
/* Check if address is aligned at the requested boundary */
|
||||||
#define IS_ALIGNED(addr, align) ((addr & (align - 1U)) == 0U)
|
#define IS_ALIGNED(addr, align) ((addr & (align - 1U)) == 0U)
|
||||||
|
|
||||||
/* Define some special cases */
|
/* Define some special cases (bitfield) */
|
||||||
#define NO_SPECIAL_CASE 0
|
#define NO_SPECIAL_CASE 0
|
||||||
#define SPECIAL_CASE_DOUBLE_MAP 1
|
#define SPECIAL_CASE_DOUBLE_MAP 1
|
||||||
#define SPECIAL_CASE_NO_FREE 2
|
#define SPECIAL_CASE_NO_FREE 2
|
||||||
#define SPECIAL_CASE_NO_VM_AREA 3
|
#define SPECIAL_CASE_NO_VM_AREA 4
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helper function used to create custom SGTs from a list of SGLs.
|
* Helper function used to create custom SGTs from a list of SGLs.
|
||||||
@@ -545,28 +545,30 @@ static int map_buffer(struct unit_module *m,
|
|||||||
goto free_sgt_os_buf;
|
goto free_sgt_os_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fixed_gpu_va && (subcase != SPECIAL_CASE_NO_VM_AREA)) {
|
if (fixed_gpu_va) {
|
||||||
size_t num_pages = DIV_ROUND_UP(buf_size, page_size);
|
|
||||||
u64 gpu_va_copy = gpu_va;
|
|
||||||
|
|
||||||
unit_info(m, "Allocating VM Area for fixed GPU VA mapping\n");
|
|
||||||
ret = nvgpu_vm_area_alloc(vm,
|
|
||||||
num_pages,
|
|
||||||
page_size,
|
|
||||||
&gpu_va_copy,
|
|
||||||
NVGPU_VM_AREA_ALLOC_FIXED_OFFSET);
|
|
||||||
if (ret != 0) {
|
|
||||||
unit_err(m, "Failed to allocate a VM area\n");
|
|
||||||
ret = UNIT_FAIL;
|
|
||||||
goto free_sgt_os_buf;
|
|
||||||
}
|
|
||||||
if (gpu_va_copy != gpu_va) {
|
|
||||||
unit_err(m, "VM area created at the wrong GPU VA\n");
|
|
||||||
ret = UNIT_FAIL;
|
|
||||||
goto free_vm_area;
|
|
||||||
}
|
|
||||||
|
|
||||||
flags |= NVGPU_VM_MAP_FIXED_OFFSET;
|
flags |= NVGPU_VM_MAP_FIXED_OFFSET;
|
||||||
|
|
||||||
|
if (!(subcase & SPECIAL_CASE_NO_VM_AREA)) {
|
||||||
|
size_t num_pages = DIV_ROUND_UP(buf_size, page_size);
|
||||||
|
u64 gpu_va_copy = gpu_va;
|
||||||
|
|
||||||
|
unit_info(m, "Allocating VM Area for fixed GPU VA mapping\n");
|
||||||
|
ret = nvgpu_vm_area_alloc(vm,
|
||||||
|
num_pages,
|
||||||
|
page_size,
|
||||||
|
&gpu_va_copy,
|
||||||
|
NVGPU_VM_AREA_ALLOC_FIXED_OFFSET);
|
||||||
|
if (ret != 0) {
|
||||||
|
unit_err(m, "Failed to allocate a VM area\n");
|
||||||
|
ret = UNIT_FAIL;
|
||||||
|
goto free_sgt_os_buf;
|
||||||
|
}
|
||||||
|
if (gpu_va_copy != gpu_va) {
|
||||||
|
unit_err(m, "VM area created at the wrong GPU VA\n");
|
||||||
|
ret = UNIT_FAIL;
|
||||||
|
goto free_vm_area;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_NVGPU_COMPRESSION
|
#ifdef CONFIG_NVGPU_COMPRESSION
|
||||||
@@ -599,7 +601,7 @@ static int map_buffer(struct unit_module *m,
|
|||||||
* Make nvgpu_vm_find_mapping return non-NULL to prevent the actual
|
* Make nvgpu_vm_find_mapping return non-NULL to prevent the actual
|
||||||
* mapping, thus simulating the fact that the buffer is already mapped.
|
* mapping, thus simulating the fact that the buffer is already mapped.
|
||||||
*/
|
*/
|
||||||
if (subcase == SPECIAL_CASE_DOUBLE_MAP) {
|
if (subcase & SPECIAL_CASE_DOUBLE_MAP) {
|
||||||
ret = nvgpu_vm_map(vm,
|
ret = nvgpu_vm_map(vm,
|
||||||
&os_buf,
|
&os_buf,
|
||||||
sgt,
|
sgt,
|
||||||
@@ -745,7 +747,7 @@ static int map_buffer(struct unit_module *m,
|
|||||||
ret = UNIT_SUCCESS;
|
ret = UNIT_SUCCESS;
|
||||||
|
|
||||||
free_mapped_buf:
|
free_mapped_buf:
|
||||||
if ((mapped_buf != NULL) && (subcase != SPECIAL_CASE_NO_FREE)) {
|
if ((mapped_buf != NULL) && !(subcase & SPECIAL_CASE_NO_FREE)) {
|
||||||
nvgpu_vm_unmap(vm, mapped_buf->addr, batch);
|
nvgpu_vm_unmap(vm, mapped_buf->addr, batch);
|
||||||
/*
|
/*
|
||||||
* Unmapping an already unmapped buffer should not cause any
|
* Unmapping an already unmapped buffer should not cause any
|
||||||
@@ -754,7 +756,7 @@ free_mapped_buf:
|
|||||||
nvgpu_vm_unmap(vm, mapped_buf->addr, batch);
|
nvgpu_vm_unmap(vm, mapped_buf->addr, batch);
|
||||||
}
|
}
|
||||||
free_vm_area:
|
free_vm_area:
|
||||||
if (fixed_gpu_va && (subcase != SPECIAL_CASE_NO_FREE)) {
|
if (fixed_gpu_va && !(subcase & SPECIAL_CASE_NO_FREE)) {
|
||||||
ret = nvgpu_vm_area_free(vm, gpu_va);
|
ret = nvgpu_vm_area_free(vm, gpu_va);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
unit_err(m, "Failed to free vm area\n");
|
unit_err(m, "Failed to free vm area\n");
|
||||||
@@ -1667,6 +1669,177 @@ exit:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int test_vm_area_error_cases(struct unit_module *m, struct gk20a *g,
|
||||||
|
void *__args)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct vm_gk20a *vm = create_test_vm(m, g);
|
||||||
|
struct nvgpu_vm_area *pvm_area = NULL;
|
||||||
|
u64 map_addr = 0;
|
||||||
|
u64 map_size = 0;
|
||||||
|
u32 pgsz_idx = 0;
|
||||||
|
struct nvgpu_posix_fault_inj *kmem_fi =
|
||||||
|
nvgpu_kmem_get_fault_injection();
|
||||||
|
/* Arbitrary address in the range of the VM created by create_test_vm */
|
||||||
|
u64 gpu_va = 0x4100000;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Failure: "fixed offset mapping with invalid map_size"
|
||||||
|
* The mapped size is 0.
|
||||||
|
*/
|
||||||
|
ret = nvgpu_vm_area_validate_buffer(vm, map_addr, map_size, pgsz_idx,
|
||||||
|
&pvm_area);
|
||||||
|
if (ret != -EINVAL) {
|
||||||
|
unit_err(m, "area_validate_buffer did not fail as expected (1).\n");
|
||||||
|
ret = UNIT_FAIL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Failure: "map offset must be buffer page size aligned"
|
||||||
|
* The mapped address is not aligned to the page size.
|
||||||
|
*/
|
||||||
|
map_addr = 0x121;
|
||||||
|
map_size = SZ_1M;
|
||||||
|
ret = nvgpu_vm_area_validate_buffer(vm, map_addr, map_size, pgsz_idx,
|
||||||
|
&pvm_area);
|
||||||
|
if (ret != -EINVAL) {
|
||||||
|
unit_err(m, "area_validate_buffer did not fail as expected (2).\n");
|
||||||
|
ret = UNIT_FAIL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Failure: "fixed offset mapping without space allocation"
|
||||||
|
* The VM has no VM area.
|
||||||
|
*/
|
||||||
|
map_addr = gpu_va;
|
||||||
|
map_size = SZ_4K;
|
||||||
|
ret = nvgpu_vm_area_validate_buffer(vm, map_addr, map_size, pgsz_idx,
|
||||||
|
&pvm_area);
|
||||||
|
if (ret != -EINVAL) {
|
||||||
|
unit_err(m, "area_validate_buffer did not fail as expected (3).\n");
|
||||||
|
ret = UNIT_FAIL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* To continue testing nvgpu_vm_area_validate_buffer, we now need
|
||||||
|
* a VM area. First target error cases for nvgpu_vm_area_alloc and then
|
||||||
|
* create a 10-page VM_AREA and assign it to the VM and enable sparse
|
||||||
|
* support to cover extra corner cases.
|
||||||
|
*/
|
||||||
|
/* Failure: invalid page size (SZ_1G) */
|
||||||
|
ret = nvgpu_vm_area_alloc(vm, 10, SZ_1G, &gpu_va, 0);
|
||||||
|
if (ret != -EINVAL) {
|
||||||
|
unit_err(m, "nvgpu_vm_area_alloc did not fail as expected (4).\n");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Failure: big page size in a VM that does not support it */
|
||||||
|
vm->big_pages = false;
|
||||||
|
ret = nvgpu_vm_area_alloc(vm, 10, SZ_64K, &gpu_va, 0);
|
||||||
|
vm->big_pages = true;
|
||||||
|
if (ret != -EINVAL) {
|
||||||
|
unit_err(m, "nvgpu_vm_area_alloc did not fail as expected (4).\n");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Failure: Dynamic allocation of vm_area fails */
|
||||||
|
nvgpu_posix_enable_fault_injection(kmem_fi, true, 0);
|
||||||
|
ret = nvgpu_vm_area_alloc(vm, 10, SZ_4K, &gpu_va, 0);
|
||||||
|
nvgpu_posix_enable_fault_injection(kmem_fi, false, 0);
|
||||||
|
if (ret != -ENOMEM) {
|
||||||
|
unit_err(m, "nvgpu_vm_area_alloc did not fail as expected (5).\n");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Failure: Dynamic allocation in nvgpu_vm_area_alloc_memory fails */
|
||||||
|
nvgpu_posix_enable_fault_injection(kmem_fi, true, 1);
|
||||||
|
ret = nvgpu_vm_area_alloc(vm, 10, SZ_4K, &gpu_va, 0);
|
||||||
|
nvgpu_posix_enable_fault_injection(kmem_fi, false, 0);
|
||||||
|
if (ret != -ENOMEM) {
|
||||||
|
unit_err(m, "nvgpu_vm_area_alloc did not fail as expected (5).\n");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Failure: Dynamic allocation in nvgpu_vm_area_alloc_gmmu_map fails */
|
||||||
|
nvgpu_posix_enable_fault_injection(kmem_fi, true, 33);
|
||||||
|
ret = nvgpu_vm_area_alloc(vm, 10, SZ_4K, &gpu_va,
|
||||||
|
NVGPU_VM_AREA_ALLOC_SPARSE);
|
||||||
|
nvgpu_posix_enable_fault_injection(kmem_fi, false, 0);
|
||||||
|
if (ret != -ENOMEM) {
|
||||||
|
unit_err(m, "nvgpu_vm_area_alloc did not fail as expected (5).\n");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now make nvgpu_vm_area_alloc succeed to be able to continue testing
|
||||||
|
* failures within nvgpu_vm_area_validate_buffer.
|
||||||
|
*/
|
||||||
|
ret = nvgpu_vm_area_alloc(vm, 10, SZ_4K, &gpu_va,
|
||||||
|
NVGPU_VM_AREA_ALLOC_SPARSE);
|
||||||
|
if (ret != 0) {
|
||||||
|
unit_err(m, "nvgpu_vm_area_alloc failed.\n");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Failure: "fixed offset mapping size overflows va node"
|
||||||
|
* Make the mapped size bigger than the VA space.
|
||||||
|
*/
|
||||||
|
map_addr = gpu_va;
|
||||||
|
map_size = SZ_4K + 128*SZ_1G;
|
||||||
|
ret = nvgpu_vm_area_validate_buffer(vm, map_addr, map_size, pgsz_idx,
|
||||||
|
&pvm_area);
|
||||||
|
if (ret != -EINVAL) {
|
||||||
|
unit_err(m, "area_validate_buffer did not fail as expected (5).\n");
|
||||||
|
ret = UNIT_FAIL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Failure: "overlapping buffer map requested"
|
||||||
|
* Map the buffer, then try to validate the same buffer again.
|
||||||
|
*/
|
||||||
|
map_addr = gpu_va + SZ_4K;
|
||||||
|
map_size = SZ_4K;
|
||||||
|
ret = map_buffer(m,
|
||||||
|
g,
|
||||||
|
vm,
|
||||||
|
NULL,
|
||||||
|
map_addr,
|
||||||
|
map_addr,
|
||||||
|
map_size,
|
||||||
|
SZ_4K,
|
||||||
|
SZ_4K,
|
||||||
|
SPECIAL_CASE_NO_VM_AREA | SPECIAL_CASE_NO_FREE);
|
||||||
|
if (ret != UNIT_SUCCESS) {
|
||||||
|
unit_err(m, "4KB buffer mapping failed\n");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
ret = nvgpu_vm_area_validate_buffer(vm, map_addr, map_size, pgsz_idx,
|
||||||
|
&pvm_area);
|
||||||
|
|
||||||
|
if (ret != -EINVAL) {
|
||||||
|
unit_err(m, "area_validate_buffer did not fail as expected (5).\n");
|
||||||
|
ret = UNIT_FAIL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = UNIT_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
/*
|
||||||
|
* The mapped buffer is not explicitly freed because it will be taken
|
||||||
|
* care of by nvgpu_vm_area_free, thus increasing code coverage.
|
||||||
|
*/
|
||||||
|
nvgpu_vm_area_free(vm, gpu_va);
|
||||||
|
nvgpu_vm_put(vm);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
struct unit_module_test vm_tests[] = {
|
struct unit_module_test vm_tests[] = {
|
||||||
/*
|
/*
|
||||||
* Requirement verification tests
|
* Requirement verification tests
|
||||||
@@ -1683,6 +1856,7 @@ struct unit_module_test vm_tests[] = {
|
|||||||
UNIT_TEST(nvgpu_vm_alloc_va, test_nvgpu_vm_alloc_va, NULL, 0),
|
UNIT_TEST(nvgpu_vm_alloc_va, test_nvgpu_vm_alloc_va, NULL, 0),
|
||||||
UNIT_TEST(vm_bind, test_vm_bind, NULL, 0),
|
UNIT_TEST(vm_bind, test_vm_bind, NULL, 0),
|
||||||
UNIT_TEST(vm_aspace_id, test_vm_aspace_id, NULL, 0),
|
UNIT_TEST(vm_aspace_id, test_vm_aspace_id, NULL, 0),
|
||||||
|
UNIT_TEST(vm_area_error_cases, test_vm_area_error_cases, NULL, 0),
|
||||||
UNIT_TEST_REQ("NVGPU-RQCD-45.C2",
|
UNIT_TEST_REQ("NVGPU-RQCD-45.C2",
|
||||||
VM_REQ1_UID,
|
VM_REQ1_UID,
|
||||||
"V5",
|
"V5",
|
||||||
|
|||||||
@@ -306,6 +306,48 @@ int test_vm_bind(struct unit_module *m, struct gk20a *g, void *__args);
|
|||||||
*/
|
*/
|
||||||
int test_vm_aspace_id(struct unit_module *m, struct gk20a *g, void *__args);
|
int test_vm_aspace_id(struct unit_module *m, struct gk20a *g, void *__args);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test specification for: test_vm_area_error_cases
|
||||||
|
*
|
||||||
|
* Description: This test targets the nvgpu_vm_area_validate_buffer and
|
||||||
|
* nvgpu_vm_area_alloc APIs.
|
||||||
|
*
|
||||||
|
* Test Type: Feature based, Error injection
|
||||||
|
*
|
||||||
|
* Input: None
|
||||||
|
*
|
||||||
|
* Steps:
|
||||||
|
* - Initialize a VM with the following characteristics:
|
||||||
|
* - 64KB large page support enabled
|
||||||
|
* - Low hole size = 64MB
|
||||||
|
* - Address space size = 128GB
|
||||||
|
* - Kernel reserved space size = 4GB
|
||||||
|
* - Try to validate a buffer of size 0 and ensure nvgpu_vm_area_validate_buffer
|
||||||
|
* returns -EINVAL.
|
||||||
|
* - Try to validate a buffer where the address to be mapped is not aligned to
|
||||||
|
* the page size and ensure that it returns -EINVAL.
|
||||||
|
* - Try to validate a buffer with a fixed address when the VM has no VM area
|
||||||
|
* and ensure that it returns -EINVAL.
|
||||||
|
* - Try to create a VM area with an invalid page size and ensure that
|
||||||
|
* nvgpu_vm_area_alloc returns -EINVAL.
|
||||||
|
* - Try to create a VM area with big page size in a VM that explicitly does
|
||||||
|
* not support big pages and ensure it returns -EINVAL.
|
||||||
|
* - Inject memory allocation errors to target various allocations within
|
||||||
|
* the nvgpu_vm_area_alloc (or its subfunctions) and ensure that it returns
|
||||||
|
* the -ENOMEM value.
|
||||||
|
* - Properly create a VM area and assign it to the test VM for the remainder
|
||||||
|
* of this test.
|
||||||
|
* - Try to validate a buffer where the mapped size is bigger than the VA space
|
||||||
|
* and ensure it returns -EINVAL.
|
||||||
|
* - Map a test buffer and ensure the mapping succeeded.
|
||||||
|
* - Try to validate the same, already mapped, test buffer and ensure that it
|
||||||
|
* returns -EINVAL.
|
||||||
|
* - Uninitialize the VM and VM area.
|
||||||
|
*
|
||||||
|
* Output: Returns PASS if the steps above were executed successfully. FAIL
|
||||||
|
* otherwise.
|
||||||
|
*/
|
||||||
|
int test_vm_area_error_cases(struct unit_module *m, struct gk20a *g,
|
||||||
|
void *__args);
|
||||||
/** }@ */
|
/** }@ */
|
||||||
#endif /* UNIT_VM_H */
|
#endif /* UNIT_VM_H */
|
||||||
|
|||||||
Reference in New Issue
Block a user