590.44.01

This commit is contained in:
Maneet Singh
2025-12-02 15:32:25 -08:00
parent 2af9f1f0f7
commit a5bfb10e75
954 changed files with 421883 additions and 408177 deletions

View File

@@ -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, &params->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;