mirror of
https://github.com/NVIDIA/open-gpu-kernel-modules.git
synced 2026-02-25 09:23:59 +00:00
590.44.01
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
Copyright (c) 2015-2024 NVIDIA Corporation
|
||||
Copyright (c) 2015-2025 NVIDIA Corporation
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
@@ -1009,166 +1009,6 @@ NV_STATUS uvm_test_pmm_async_alloc(UVM_TEST_PMM_ASYNC_ALLOC_PARAMS *params, stru
|
||||
return status;
|
||||
}
|
||||
|
||||
static uvm_reverse_map_t g_reverse_map_entries[PAGES_PER_UVM_VA_BLOCK * 4];
|
||||
|
||||
static NV_STATUS test_pmm_reverse_map_single(uvm_gpu_t *gpu, uvm_va_space_t *va_space, NvU64 addr)
|
||||
{
|
||||
NV_STATUS status = NV_OK;
|
||||
NvU32 num_translations;
|
||||
uvm_va_block_t *va_block;
|
||||
uvm_gpu_phys_address_t phys_addr;
|
||||
bool is_resident;
|
||||
|
||||
status = uvm_va_block_find(va_space, addr, &va_block);
|
||||
if (status != NV_OK)
|
||||
return status;
|
||||
|
||||
TEST_CHECK_RET(uvm_va_block_size(va_block) == UVM_VA_BLOCK_SIZE);
|
||||
|
||||
// Verify that all pages are populated on the GPU
|
||||
uvm_mutex_lock(&va_block->lock);
|
||||
|
||||
is_resident = uvm_processor_mask_test(&va_block->resident, gpu->id) &&
|
||||
uvm_page_mask_full(uvm_va_block_resident_mask_get(va_block, gpu->id, NUMA_NO_NODE));
|
||||
if (is_resident)
|
||||
phys_addr = uvm_va_block_gpu_phys_page_address(va_block, 0, gpu);
|
||||
|
||||
uvm_mutex_unlock(&va_block->lock);
|
||||
|
||||
TEST_CHECK_RET(is_resident);
|
||||
|
||||
// In this test a single VA range covers the whole 2MB physical region. We
|
||||
// expect a single translation to be returned for a 2MB chunk.
|
||||
num_translations = uvm_pmm_gpu_phys_to_virt(&gpu->pmm, phys_addr.address, UVM_VA_BLOCK_SIZE, g_reverse_map_entries);
|
||||
TEST_CHECK_RET(num_translations == 1);
|
||||
TEST_CHECK_RET(g_reverse_map_entries[0].va_block == va_block);
|
||||
TEST_CHECK_RET(g_reverse_map_entries[0].region.first == 0);
|
||||
TEST_CHECK_RET(uvm_va_block_region_num_pages(g_reverse_map_entries[0].region) == uvm_va_block_num_cpu_pages(va_block));
|
||||
|
||||
uvm_va_block_release(va_block);
|
||||
|
||||
return NV_OK;
|
||||
}
|
||||
|
||||
static NV_STATUS test_pmm_reverse_map_many_blocks(uvm_gpu_t *gpu, uvm_va_space_t *va_space, NvU64 addr, NvU64 size)
|
||||
{
|
||||
uvm_va_range_managed_t *managed_range;
|
||||
uvm_va_block_t *va_block = NULL;
|
||||
uvm_va_block_context_t *va_block_context = NULL;
|
||||
NvU32 num_blocks;
|
||||
NvU32 index = 0;
|
||||
uvm_gpu_phys_address_t phys_addr = {0};
|
||||
bool is_resident;
|
||||
|
||||
// In this test, the [addr:addr + size) VA region contains
|
||||
// several managed ranges with different sizes.
|
||||
|
||||
// Find the first block to compute the base physical address of the root
|
||||
// chunk
|
||||
uvm_for_each_va_range_managed_in(managed_range, va_space, addr, addr + size - 1) {
|
||||
va_block = uvm_va_range_block(managed_range, 0);
|
||||
if (va_block)
|
||||
break;
|
||||
}
|
||||
TEST_CHECK_RET(va_block);
|
||||
|
||||
va_block_context = uvm_va_block_context_alloc(NULL);
|
||||
TEST_CHECK_RET(va_block_context);
|
||||
|
||||
uvm_mutex_lock(&va_block->lock);
|
||||
|
||||
is_resident = uvm_id_equal(uvm_va_block_page_get_closest_resident(va_block, va_block_context, 0, gpu->id), gpu->id);
|
||||
if (is_resident) {
|
||||
phys_addr = uvm_va_block_gpu_phys_page_address(va_block, 0, gpu);
|
||||
phys_addr.address = UVM_ALIGN_DOWN(phys_addr.address, UVM_VA_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
uvm_mutex_unlock(&va_block->lock);
|
||||
|
||||
uvm_va_block_context_free(va_block_context);
|
||||
|
||||
TEST_CHECK_RET(is_resident);
|
||||
|
||||
// Perform the lookup for the whole root chunk
|
||||
num_blocks = uvm_pmm_gpu_phys_to_virt(&gpu->pmm, phys_addr.address, size, g_reverse_map_entries);
|
||||
TEST_CHECK_RET(num_blocks != 0);
|
||||
|
||||
// Iterate over all managed ranges and their VA blocks within the 2MB VA
|
||||
// region. Some blocks are not populated. However, we assume that blocks
|
||||
// have been populated in order so they have been assigned physical
|
||||
// addresses incrementally. Therefore, the reverse translations will show
|
||||
// them in order.
|
||||
uvm_for_each_va_range_managed_in(managed_range, va_space, addr, addr + size - 1) {
|
||||
for_each_va_block_in_va_range(managed_range, va_block) {
|
||||
NvU32 num_va_block_pages = 0;
|
||||
|
||||
// Iterate over all the translations for the current VA block. One
|
||||
// translation per chunk is returned. We compute the total number of
|
||||
// pages covered in the translations to check that they match with
|
||||
// the number of pages in the VA block.
|
||||
while (g_reverse_map_entries[index].va_block == va_block) {
|
||||
uvm_reverse_map_t *reverse_mapping;
|
||||
|
||||
reverse_mapping = &g_reverse_map_entries[index];
|
||||
|
||||
uvm_va_block_release(va_block);
|
||||
num_va_block_pages += uvm_va_block_region_num_pages(reverse_mapping->region);
|
||||
UVM_ASSERT(uvm_va_block_contains_address(va_block, uvm_reverse_map_start(reverse_mapping)));
|
||||
UVM_ASSERT(uvm_va_block_contains_address(va_block, uvm_reverse_map_end(reverse_mapping)));
|
||||
|
||||
uvm_mutex_lock(&va_block->lock);
|
||||
|
||||
// Verify that all pages are populated on the GPU
|
||||
is_resident = uvm_page_mask_region_full(uvm_va_block_resident_mask_get(va_block, gpu->id, NUMA_NO_NODE),
|
||||
reverse_mapping->region);
|
||||
|
||||
uvm_mutex_unlock(&va_block->lock);
|
||||
|
||||
TEST_CHECK_RET(is_resident);
|
||||
|
||||
++index;
|
||||
}
|
||||
|
||||
if (num_va_block_pages)
|
||||
TEST_CHECK_RET(num_va_block_pages == uvm_va_block_num_cpu_pages(va_block));
|
||||
}
|
||||
}
|
||||
TEST_CHECK_RET(index == num_blocks);
|
||||
|
||||
return NV_OK;
|
||||
}
|
||||
|
||||
NV_STATUS uvm_test_pmm_reverse_map(UVM_TEST_PMM_REVERSE_MAP_PARAMS *params, struct file *filp)
|
||||
{
|
||||
NV_STATUS status;
|
||||
uvm_gpu_t *gpu;
|
||||
uvm_va_space_t *va_space;
|
||||
|
||||
va_space = uvm_va_space_get(filp);
|
||||
|
||||
// Take the global lock to void interferences from different instances of
|
||||
// the test, since we use global variables
|
||||
uvm_mutex_lock(&g_uvm_global.global_lock);
|
||||
uvm_va_space_down_write(va_space);
|
||||
|
||||
gpu = uvm_va_space_get_gpu_by_uuid(va_space, ¶ms->gpu_uuid);
|
||||
if (!gpu || !uvm_processor_mask_test(&va_space->registered_gpus, gpu->id)) {
|
||||
status = NV_ERR_INVALID_DEVICE;
|
||||
goto exit_unlock;
|
||||
}
|
||||
|
||||
status = test_pmm_reverse_map_single(gpu, va_space, params->range_address1);
|
||||
|
||||
if (status == NV_OK)
|
||||
status = test_pmm_reverse_map_many_blocks(gpu, va_space, params->range_address2, params->range_size2);
|
||||
|
||||
exit_unlock:
|
||||
uvm_va_space_up_write(va_space);
|
||||
uvm_mutex_unlock(&g_uvm_global.global_lock);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static NV_STATUS test_chunk_with_elevated_page(uvm_gpu_t *gpu)
|
||||
{
|
||||
uvm_pmm_gpu_t *pmm = &gpu->pmm;
|
||||
|
||||
Reference in New Issue
Block a user