diff options
Diffstat (limited to 'legacy-driver-guest/kernel-tests/gsp_vgpu_mock_test.c')
| -rw-r--r-- | legacy-driver-guest/kernel-tests/gsp_vgpu_mock_test.c | 624 |
1 files changed, 0 insertions, 624 deletions
diff --git a/legacy-driver-guest/kernel-tests/gsp_vgpu_mock_test.c b/legacy-driver-guest/kernel-tests/gsp_vgpu_mock_test.c deleted file mode 100644 index b9a46df..0000000 --- a/legacy-driver-guest/kernel-tests/gsp_vgpu_mock_test.c +++ /dev/null @@ -1,624 +0,0 @@ -/* - * GSP vGPU-IO Driver Mock Test - * Tests driver logic with mocked hardware interfaces - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/string.h> -#include <linux/errno.h> -#include <linux/mutex.h> -#include <linux/list.h> -#include <linux/idr.h> -#include <linux/kref.h> -#include <linux/completion.h> -#include <linux/atomic.h> - -#define TEST_PASS 0 -#define TEST_FAIL -1 - -static int test_count = 0; -static int pass_count = 0; -static int fail_count = 0; - -#define TEST_ASSERT(cond, msg) \ - do { \ - test_count++; \ - if (cond) { \ - pass_count++; \ - pr_info("PASS: %s\n", msg); \ - } else { \ - fail_count++; \ - pr_err("FAIL: %s\n", msg); \ - } \ - } while (0) - -#define TEST_ASSERT_EQ(a, b, msg) \ - TEST_ASSERT((a) == (b), msg " (expected " #b ", got " #a ")") - -/* ============================================================ - * Mock Hardware Abstraction - * ============================================================ */ - -struct mock_hw { - u64 bar0_regs[256]; - u64 bar1_regs[256]; - u8 *fw_memory; - size_t fw_size; - bool doorbell_triggered; - u32 doorbell_count; - spinlock_t lock; -}; - -static struct mock_hw *mock_hw_create(void) -{ - struct mock_hw *hw = kzalloc(sizeof(*hw), GFP_KERNEL); - if (!hw) - return NULL; - - hw->fw_memory = vmalloc(32 * 1024 * 1024); // 32MB - if (!hw->fw_memory) { - kfree(hw); - return NULL; - } - hw->fw_size = 32 * 1024 * 1024; - spin_lock_init(&hw->lock); - return hw; -} - -static void mock_hw_destroy(struct mock_hw *hw) -{ - if (!hw) - return; - vfree(hw->fw_memory); - kfree(hw); -} - -static void mock_hw_write_bar0(struct mock_hw *hw, u32 offset, u32 value) -{ - unsigned long flags; - spin_lock_irqsave(&hw->lock, flags); - if (offset / 4 < 256) - hw->bar0_regs[offset / 4] = value; - if (offset == 0x1000) { // Doorbell - hw->doorbell_triggered = true; - hw->doorbell_count++; - } - spin_unlock_irqrestore(&hw->lock, flags); -} - -static u32 mock_hw_read_bar0(struct mock_hw *hw, u32 offset) -{ - unsigned long flags; - u32 value = 0; - spin_lock_irqsave(&hw->lock, flags); - if (offset / 4 < 256) - value = hw->bar0_regs[offset / 4]; - spin_unlock_irqrestore(&hw->lock, flags); - return value; -} - -static void mock_hw_write_bar1(struct mock_hw *hw, u64 offset, u64 value) -{ - unsigned long flags; - spin_lock_irqsave(&hw->lock, flags); - if (offset < hw->fw_size) - *(u64 *)(hw->fw_memory + offset) = value; - spin_unlock_irqrestore(&hw->lock, flags); -} - -static u64 mock_hw_read_bar1(struct mock_hw *hw, u64 offset) -{ - unsigned long flags; - u64 value = 0; - spin_lock_irqsave(&hw->lock, flags); - if (offset < hw->fw_size) - value = *(u64 *)(hw->fw_memory + offset); - spin_unlock_irqrestore(&hw->lock, flags); - return value; -} - -/* ============================================================ - * Mock VF Operations - * ============================================================ */ - -struct mock_vf { - u32 id; - u64 bar1_offset; - u64 bar1_size; - u64 pt_base; - u64 pt_size; - u64 cmd_base; - u64 cmd_size; - bool active; - struct { - u64 aperture_offset; - u64 aperture_size; - bool force_access; - u32 force_vf; - } bar_state; - struct list_head wpr_list; - struct mutex lock; -}; - -struct mock_wpr_region { - struct list_head list; - u64 base; - u64 size; - u32 flags; -}; - -static struct mock_vf *mock_vf_create(u32 id, u64 bar1_offset, u64 bar1_size, - u64 pt_base, u64 pt_size, - u64 cmd_base, u64 cmd_size) -{ - struct mock_vf *vf = kzalloc(sizeof(*vf), GFP_KERNEL); - if (!vf) - return NULL; - - vf->id = id; - vf->bar1_offset = bar1_offset; - vf->bar1_size = bar1_size; - vf->pt_base = pt_base; - vf->pt_size = pt_size; - vf->cmd_base = cmd_base; - vf->cmd_size = cmd_size; - vf->active = true; - INIT_LIST_HEAD(&vf->wpr_list); - mutex_init(&vf->lock); - - vf->bar_state.aperture_offset = bar1_offset; - vf->bar_state.aperture_size = bar1_size; - vf->bar_state.force_access = false; - vf->bar_state.force_vf = 0; - - return vf; -} - -static void mock_vf_destroy(struct mock_vf *vf) -{ - if (!vf) - return; - - struct mock_wpr_region *rgn, *tmp; - mutex_lock(&vf->lock); - list_for_each_entry_safe(rgn, tmp, &vf->wpr_list, list) { - list_del(&rgn->list); - kfree(rgn); - } - mutex_unlock(&vf->lock); - - kfree(vf); -} - -static int mock_vf_wpr_add(struct mock_vf *vf, u64 base, u64 size, u32 flags) -{ - struct mock_wpr_region *rgn = kzalloc(sizeof(*rgn), GFP_KERNEL); - if (!rgn) - return -ENOMEM; - - rgn->base = base; - rgn->size = size; - rgn->flags = flags; - - mutex_lock(&vf->lock); - list_add(&rgn->list, &vf->wpr_list); - mutex_unlock(&vf->lock); - - return 0; -} - -static int mock_vf_wpr_remove(struct mock_vf *vf, u64 base) -{ - struct mock_wpr_region *rgn, *tmp; - bool found = false; - - mutex_lock(&vf->lock); - list_for_each_entry_safe(rgn, tmp, &vf->wpr_list, list) { - if (rgn->base == base) { - list_del(&rgn->list); - kfree(rgn); - found = true; - break; - } - } - mutex_unlock(&vf->lock); - - return found ? 0 : -ENOENT; -} - -/* ============================================================ - * Mock RPC Client - * ============================================================ */ - -struct mock_rpc_client { - u32 seq; - u32 pending_seq[64]; - u32 pending_count; - struct mutex lock; -}; - -static struct mock_rpc_client *mock_rpc_create(void) -{ - struct mock_rpc_client *rpc = kzalloc(sizeof(*rpc), GFP_KERNEL); - if (!rpc) - return NULL; - mutex_init(&rpc->lock); - return rpc; -} - -static void mock_rpc_destroy(struct mock_rpc_client *rpc) -{ - if (!rpc) - return; - kfree(rpc); -} - -static int mock_rpc_send(struct mock_rpc_client *rpc, u32 rpc_type, - void *payload, size_t payload_size, - void *response, size_t *response_size) -{ - if (!rpc) - return -EINVAL; - - mutex_lock(&rpc->lock); - rpc->seq++; - rpc->pending_seq[rpc->pending_count++] = rpc->seq; - mutex_unlock(&rpc->lock); - - /* Simulate successful response */ - if (response && response_size) { - struct gsp_rpc_response *resp = response; - resp->status = 0; - resp->rpc_type = rpc_type; - resp->sequence = rpc->seq; - *response_size = sizeof(*resp); - } - - return 0; -} - -/* ============================================================ - * Driver Logic Tests with Mocks - * ============================================================ */ - -static int test_mock_hardware(void) -{ - struct mock_hw *hw = mock_hw_create(); - TEST_ASSERT(hw != NULL, "Mock HW create"); - - /* Test BAR0 write/read */ - mock_hw_write_bar0(hw, 0x1000, 0x1); - TEST_ASSERT(hw->doorbell_triggered, "Doorbell triggered"); - TEST_ASSERT_EQ(hw->doorbell_count, 1, "Doorbell count"); - - u32 val = mock_hw_read_bar0(hw, 0x1000); - TEST_ASSERT_EQ(val, 0x1, "BAR0 read back"); - - /* Test BAR1 write/read */ - mock_hw_write_bar1(hw, 0x1000, 0xDEADBEEFCAFEBABE); - u64 val64 = mock_hw_read_bar1(hw, 0x1000); - TEST_ASSERT_EQ(val64, 0xDEADBEEFCAFEBABE, "BAR1 read back"); - - mock_hw_destroy(hw); - return TEST_PASS; -} - -static int test_mock_vf_lifecycle(void) -{ - struct mock_vf *vf = mock_vf_create(1, 0x10000000, 0x100000, - 0x20000000, 0x100000, - 0x30000000, 0x10000); - TEST_ASSERT(vf != NULL, "Mock VF create"); - - TEST_ASSERT(vf->active, "VF active after create"); - TEST_ASSERT_EQ(vf->id, 1, "VF ID"); - TEST_ASSERT_EQ(vf->bar1_offset, 0x10000000, "BAR1 offset"); - TEST_ASSERT_EQ(vf->bar1_size, 0x100000, "BAR1 size"); - TEST_ASSERT_EQ(vf->pt_base, 0x20000000, "Page table base"); - TEST_ASSERT_EQ(vf->pt_size, 0x100000, "Page table size"); - - /* Test BAR state */ - TEST_ASSERT_EQ(vf->bar_state.aperture_offset, 0x10000000, "Aperture offset"); - TEST_ASSERT_EQ(vf->bar_state.aperture_size, 0x100000, "Aperture size"); - TEST_ASSERT(!vf->bar_state.force_access, "Force access initially false"); - - /* Test WPR list empty */ - TEST_ASSERT(list_empty(&vf->wpr_list), "WPR list empty initially"); - - mock_vf_destroy(vf); - return TEST_PASS; -} - -static int test_mock_vf_wpr(void) -{ - struct mock_vf *vf = mock_vf_create(1, 0x10000000, 0x100000, - 0x20000000, 0x100000, - 0x30000000, 0x10000); - TEST_ASSERT(vf != NULL, "Mock VF create"); - - /* Add WPR region */ - int ret = mock_vf_wpr_add(vf, 0x10000000, 0x10000, 3); - TEST_ASSERT_EQ(ret, 0, "WPR add"); - - ret = mock_vf_wpr_add(vf, 0x20000000, 0x20000, 1); - TEST_ASSERT_EQ(ret, 0, "WPR add second"); - - /* Verify list */ - int count = 0; - struct mock_wpr_region *rgn; - mutex_lock(&vf->lock); - list_for_each_entry(rgn, &vf->wpr_list, list) { - count++; - } - mutex_unlock(&vf->lock); - TEST_ASSERT_EQ(count, 2, "Two WPR regions"); - - /* Remove one */ - ret = mock_vf_wpr_remove(vf, 0x10000000); - TEST_ASSERT_EQ(ret, 0, "WPR remove"); - - count = 0; - mutex_lock(&vf->lock); - list_for_each_entry(rgn, &vf->wpr_list, list) { - count++; - } - mutex_unlock(&vf->lock); - TEST_ASSERT_EQ(count, 1, "One WPR region remaining"); - - /* Remove non-existent */ - ret = mock_vf_wpr_remove(vf, 0x30000000); - TEST_ASSERT_EQ(ret, -ENOENT, "WPR remove non-existent returns ENOENT"); - - mock_vf_destroy(vf); - return TEST_PASS; -} - -static int test_mock_rpc_client(void) -{ - struct mock_rpc_client *rpc = mock_rpc_create(); - TEST_ASSERT(rpc != NULL, "Mock RPC create"); - - struct gsp_rpc_response resp; - size_t resp_size = sizeof(resp); - struct gsp_alloc_payload payload = { - .size = cpu_to_le64(0x100000), - .type = cpu_to_le32(GSP_MEM_VRAM), - }; - - int ret = mock_rpc_send(rpc, GSP_RPC_ALLOC, &payload, sizeof(payload), &resp, &resp_size); - TEST_ASSERT_EQ(ret, 0, "RPC send"); - - TEST_ASSERT_EQ(resp.status, 0, "RPC response status"); - TEST_ASSERT_EQ(resp.rpc_type, GSP_RPC_ALLOC, "RPC response type"); - TEST_ASSERT_EQ(resp.sequence, 1, "RPC response sequence"); - - /* Second call */ - ret = mock_rpc_send(rpc, GSP_RPC_PIN, &payload, sizeof(payload), &resp, &resp_size); - TEST_ASSERT_EQ(ret, 0, "RPC send second"); - TEST_ASSERT_EQ(resp.sequence, 2, "RPC response sequence 2"); - - mock_rpc_destroy(rpc); - return TEST_PASS; -} - -static int test_driver_vf_creation_logic(void) -{ - /* Simulate driver VF creation logic */ - struct mock_hw *hw = mock_hw_create(); - struct mock_rpc_client *rpc = mock_rpc_create(); - struct mock_vf *vfs[8] = {0}; - - /* Create VFs 1-4 */ - for (int i = 1; i <= 4; i++) { - vfs[i] = mock_vf_create(i, 0x10000000 * i, 0x100000, - 0x20000000 * i, 0x100000, - 0x30000000 * i, 0x10000); - TEST_ASSERT(vfs[i] != NULL, "VF creation in loop"); - TEST_ASSERT(vfs[i]->active, "VF active in loop"); - } - - /* Initialize BAR for each VF */ - for (int i = 1; i <= 4; i++) { - vfs[i]->bar_state.aperture_offset = vfs[i]->bar1_offset; - vfs[i]->bar_state.aperture_size = vfs[i]->bar1_size; - TEST_ASSERT_EQ(vfs[i]->bar_state.aperture_offset, 0x10000000 * i, "VF BAR offset"); - TEST_ASSERT_EQ(vfs[i]->bar_state.aperture_size, 0x100000, "VF BAR size"); - } - - /* Add WPR for each VF */ - for (int i = 1; i <= 4; i++) { - int ret = mock_vf_wpr_add(vfs[i], vfs[i]->pt_base, vfs[i]->pt_size, 3); - TEST_ASSERT_EQ(ret, 0, "VF WPR add in loop"); - } - - /* Simulate RPC calls for each VF */ - for (int i = 1; i <= 4; i++) { - struct gsp_rpc_response resp; - size_t resp_size = sizeof(resp); - struct gsp_alloc_payload payload = { - .size = cpu_to_le64(0x100000), - .type = cpu_to_le32(GSP_MEM_VRAM), - .vf_id = cpu_to_le32(i), - }; - int ret = mock_rpc_send(rpc, GSP_RPC_ALLOC, &payload, sizeof(payload), &resp, &resp_size); - TEST_ASSERT_EQ(ret, 0, "VF RPC alloc"); - TEST_ASSERT_EQ(resp.status, 0, "VF RPC response OK"); - } - - /* Cleanup */ - for (int i = 1; i <= 4; i++) { - mock_vf_destroy(vfs[i]); - } - mock_rpc_destroy(rpc); - mock_hw_destroy(hw); - - return TEST_PASS; -} - -static int test_migration_progress_tracking(void) -{ - struct { - u64 pages_transferred; - u64 bytes_transferred; - u64 dirty_pages; - u64 *page_list; - u32 page_count; - } progress = {0}; - - progress.page_count = 1000; - progress.page_list = kcalloc(progress.page_count, sizeof(u64), GFP_KERNEL); - TEST_ASSERT(progress.page_list != NULL, "Progress page list alloc"); - - /* Simulate transfer loop */ - for (int iter = 0; iter < 10; iter++) { - progress.pages_transferred += 100; - progress.bytes_transferred += 100 * 4096; - progress.dirty_pages = 50 - (iter * 5); - - TEST_ASSERT(progress.pages_transferred <= 1000, "Pages not exceeded"); - TEST_ASSERT(progress.bytes_transferred <= 1000 * 4096, "Bytes not exceeded"); - } - - TEST_ASSERT_EQ(progress.pages_transferred, 1000, "Final pages"); - TEST_ASSERT_EQ(progress.bytes_transferred, 1000 * 4096, "Final bytes"); - TEST_ASSERT_EQ(progress.dirty_pages, 0, "Final dirty pages"); - - kfree(progress.page_list); - return TEST_PASS; -} - -static int test_bar_state_machine(void) -{ - struct { - u64 aperture_offset; - u64 aperture_size; - bool force_access; - u32 force_vf; - } bar_state = {0}; - - /* Initial state */ - bar_state.aperture_offset = 0x10000000; - bar_state.aperture_size = 0x100000; - TEST_ASSERT_EQ(bar_state.aperture_offset, 0x10000000, "Initial aperture offset"); - TEST_ASSERT(!bar_state.force_access, "Force access initially false"); - - /* Enable force access */ - bar_state.force_access = true; - bar_state.force_vf = 1; - TEST_ASSERT(bar_state.force_access, "Force access enabled"); - TEST_ASSERT_EQ(bar_state.force_vf, 1, "Force VF set"); - - /* Disable force access */ - bar_state.force_access = false; - bar_state.force_vf = 0; - TEST_ASSERT(!bar_state.force_access, "Force access disabled"); - TEST_ASSERT_EQ(bar_state.force_vf, 0, "Force VF cleared"); - - return TEST_PASS; -} - -static int test_concurrent_vf_operations(void) -{ - struct mock_vf *vf1 = mock_vf_create(1, 0x10000000, 0x100000, 0x20000000, 0x100000, 0x30000000, 0x10000); - struct mock_vf *vf2 = mock_vf_create(2, 0x20000000, 0x100000, 0x40000000, 0x100000, 0x60000000, 0x10000); - struct mock_rpc_client *rpc = mock_rpc_create(); - - TEST_ASSERT(vf1 && vf2 && rpc, "Create two VFs and RPC"); - - /* Simulate concurrent operations */ - struct gsp_rpc_response resp; - size_t resp_size = sizeof(resp); - - /* VF1 alloc */ - struct gsp_alloc_payload payload1 = { - .size = cpu_to_le64(0x100000), - .type = cpu_to_le32(GSP_MEM_VRAM), - .vf_id = cpu_to_le32(1), - }; - int ret = mock_rpc_send(rpc, GSP_RPC_ALLOC, &payload1, sizeof(payload1), &resp, &resp_size); - TEST_ASSERT_EQ(ret, 0, "VF1 alloc"); - TEST_ASSERT_EQ(resp.status, 0, "VF1 alloc response"); - - /* VF2 alloc */ - struct gsp_alloc_payload payload2 = { - .size = cpu_to_le64(0x200000), - .type = cpu_to_le32(GSP_MEM_VRAM), - .vf_id = cpu_to_le32(2), - }; - ret = mock_rpc_send(rpc, GSP_RPC_ALLOC, &payload2, sizeof(payload2), &resp, &resp_size); - TEST_ASSERT_EQ(ret, 0, "VF2 alloc"); - TEST_ASSERT_EQ(resp.status, 0, "VF2 alloc response"); - - /* VF1 pin */ - struct gsp_pin_payload pin_payload = { - .handle = cpu_to_le64(0x1000), - .vf_id = cpu_to_le32(1), - }; - ret = mock_rpc_send(rpc, GSP_RPC_PIN, &pin_payload, sizeof(pin_payload), &resp, &resp_size); - TEST_ASSERT_EQ(ret, 0, "VF1 pin"); - - /* VF2 BAR trap */ - struct gsp_bar_trap_payload bar_payload = { - .vf_id = cpu_to_le32(2), - .bar_index = cpu_to_le32(1), - }; - ret = mock_rpc_send(rpc, GSP_RPC_BAR_TRAP, &bar_payload, sizeof(bar_payload), &resp, &resp_size); - TEST_ASSERT_EQ(ret, 0, "VF2 BAR trap"); - - /* Verify sequence numbers */ - TEST_ASSERT_EQ(resp.sequence, 4, "Sequence number 4"); - - mock_vf_destroy(vf1); - mock_vf_destroy(vf2); - mock_rpc_destroy(rpc); - - return TEST_PASS; -} - -/* ============================================================ - * Module Init/Exit - * ============================================================ */ - -static int __init gsp_mock_test_init(void) -{ - pr_info("========================================\n"); - pr_info("GSP vGPU-IO Mock Driver Test Suite\n"); - pr_info("========================================\n"); - - test_mock_hardware(); - test_mock_vf_lifecycle(); - test_mock_vf_wpr(); - test_mock_rpc_client(); - test_driver_vf_creation_logic(); - test_migration_progress_tracking(); - test_bar_state_machine(); - test_concurrent_vf_operations(); - - pr_info("========================================\n"); - pr_info("Mock Test Results: %d total, %d passed, %d failed\n", - test_count, pass_count, fail_count); - pr_info("========================================\n"); - - if (fail_count > 0) { - pr_err("MOCK TEST SUITE FAILED\n"); - return -EINVAL; - } - - pr_info("MOCK TEST SUITE PASSED\n"); - return 0; -} - -static void __exit gsp_mock_test_exit(void) -{ - pr_info("GSP vGPU-IO Mock Test Suite Exited\n"); -} - -module_init(gsp_mock_test_init); -module_exit(gsp_mock_test_exit); - -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Open-IOV Project"); -MODULE_DESCRIPTION("GSP vGPU-IO Mock Driver Test"); -MODULE_VERSION("1.0");
\ No newline at end of file |
