[RFC v3 i-g-t] tests/intel/sec_xe_exec_queue_timeslice_abuse: Validate the Impact of Timeslice Abuse on Exec Queues
Peter Senna Tschudin
peter.senna at linux.intel.com
Wed May 7 10:41:10 UTC 2025
DO NOT MERGE!
The objective is to test the behavior of the GPU scheduler under
conditions where one execution queue ("attacker") is configured with an
abnormally large timeslice, potentially disrupting the normal execution
of another queue ("attacked"). The explicit attack point is the ioctl
DRM_XE_EXEC_QUEUE_EXTENSION_SET_PROPERTY.
This temporarily disables drm and xe logging to prevent it from slowing
down and serializing the tests. Using igt_drm_debug_level_update()
ensures that the logging level is restored after this igt is done.
This RFC implements the first step that is reading timeslice values for
each engine and run the following tests on timeslice limits:
- Boundary Value Analysis: Focuses on testing at the boundaries of
input values with values such as max - 1, max, max + 1.
- Equivalence Partitioning: Divide values into partitions where all
values behave similarly and test one value from each partition.
- Fuzz Testing: Basic fuzz tester for
- Large numbers
- Empty value
- '\0'
- 10'000 u64 random values
- Fuzz stress test: Create 1000 threads and call the fuzzing test.
While this takes about 30 seconds to run, it produces several
megabytes of dmesg.
The proposed steps are (this patch goes until 2a):
1. Determine the values for the following parameters:
- `timeslice_duration_us`: Default timeslice duration in
microseconds.
- `timeslice_duration_min`: Minimum allowable timeslice duration.
- `timeslice_duration_max`: Maximum allowable timeslice duration.
2. Create two execution queues with the following configurations:
- `attacked`: Queue with standard/default settings.
- `attacker`: Queue configured with an extended timeslice
duration. The goal is to:
a) Try to set timeslice to invalid values. This is
expected to fail.
b) Create the attacker queue setting the timeslice to
`timeslice_duration_max`.
3. Submit tasks to both queues:
- Submit a workload to the `attacked` queue with normal
operations.
- Submit a workload to the `attacker` queue designed to
maximize its timeslice and potentially disrupt the GPU
scheduler.
4. Verify the behavior of the `attacked` queue:
- Ensure that tasks in the `attacked` queue execute within the
expected time constraints and are not delayed or blocked due
to the extended timeslice of the `attacker` queue.
- Specifically, confirm that tasks in the `attacked` queue do
not exceed `timeslice_duration_max` in terms of execution
delays or interruptions.
Cc: michal.winiarski at intel.com
Cc: rodrigo.vivi at intel.com
Signed-off-by: Peter Senna Tschudin <peter.senna at linux.intel.com>
---
.../intel/sec_xe_exec_queue_timeslice_abuse.c | 689 ++++++++++++++++++
tests/meson.build | 1 +
2 files changed, 690 insertions(+)
create mode 100644 tests/intel/sec_xe_exec_queue_timeslice_abuse.c
diff --git a/tests/intel/sec_xe_exec_queue_timeslice_abuse.c b/tests/intel/sec_xe_exec_queue_timeslice_abuse.c
new file mode 100644
index 000000000..abbc384c4
--- /dev/null
+++ b/tests/intel/sec_xe_exec_queue_timeslice_abuse.c
@@ -0,0 +1,689 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2025 Intel Corporation
+ */
+
+/*
+ * Test Specification: Validate the Impact of Timeslice Abuse on Exec Queues
+ *
+ * Objective
+ * Test the behavior of the GPU scheduler under conditions where one execution
+ * queue ("attacker") is configured with an abnormally large timeslice,
+ * potentially disrupting the normal execution of another queue ("attacked").
+ *
+ * Steps:
+ *
+ * For each GPU engine available:
+ * 1. Determine the values for the following parameters:
+ * - `timeslice_duration_us`: Default timeslice duration in
+ * microseconds.
+ * - `timeslice_duration_min`: Minimum allowable timeslice duration.
+ * - `timeslice_duration_max`: Maximum allowable timeslice duration.
+ *
+ * 2. Create two execution queues with the following configurations:
+ * - `attacked`: Queue with standard/default settings.
+ * - `attacker`: Queue configured with an extended timeslice
+ * duration. The goal is to:
+ * a) First attempt to set a timeslice greater than
+ * `timeslice_duration_max`.
+ * b) If setting a timeslice above `timeslice_duration_max`
+ * fails, fallback to setting the timeslice to
+ * `timeslice_duration_max`.
+ *
+ * 3. Submit tasks to both queues:
+ * - Submit a workload to the `attacked` queue with normal
+ * operations.
+ * - Submit a workload to the `attacker` queue designed to
+ * maximize its timeslice and potentially disrupt the GPU
+ * scheduler.
+ *
+ * 4. Verify the behavior of the `attacked` queue:
+ * - Ensure that tasks in the `attacked` queue execute within the
+ * expected time constraints and are not delayed or blocked due
+ * to the extended timeslice of the `attacker` queue.
+ * - Specifically, confirm that tasks in the `attacked` queue do
+ * not exceed `timeslice_duration_max` in terms of execution
+ * delays or interruptions.
+ *
+ */
+
+#include <dirent.h>
+#include <fcntl.h>
+
+#include "igt.h"
+#include "igt_list.h"
+#include "igt_sysfs.h"
+#include "xe_drm.h"
+#include "xe/xe_ioctl.h"
+#include "xe/xe_query.h"
+
+#define MAX_U64 0xFFFFFFFFFFFFFFFF
+
+static struct igt_list_head engines_list;
+
+/* Struct to Hold Data for Each Engine */
+struct engines_timeslice_test_data {
+ /* Name of the GPU engine (e.g., "CCS", "VCS", "RCS", "BCS", "VECS") */
+ const char *engine_name;
+
+ /* Minimum allowable timeslice duration (microseconds) */
+ uint32_t timeslice_min;
+
+ /* Maximum allowable timeslice duration (microseconds) */
+ uint32_t timeslice_max;
+
+ /* Timeslice value set for the attacker queue (microseconds) */
+ uint32_t timeslice_set;
+
+ /* Linked list node */
+ struct igt_list_head link;
+};
+
+/* Struct for parametric testing */
+struct timeslice_test_case {
+ uint64_t value;
+ int expected_result;
+};
+
+typedef struct {
+ int xe;
+ int vm;
+ int random_count;
+} thread_args_t;
+
+/**
+ * engines_list_add_timeslices: Check if there is already an entry in the list
+ * for the engine and add timeslices.
+ * @engine: name of the engine
+ * @set: timeslice duration set for the attacker queue
+ * @min: minimum allowable timeslice duration
+ * @max: maximum allowable timeslice duration
+ *
+ * Returns: bool indicating if timeslices were added to the list
+ *
+ */
+static bool engines_list_add_timeslices(const char *engine, uint32_t set,
+ uint32_t min, uint32_t max)
+{
+ struct engines_timeslice_test_data *engine_data = NULL;
+
+ /* Check if the engine already exists in the list. If it does
+ * add the timeslice values to the existing entry
+ */
+ igt_list_for_each_entry(engine_data, &engines_list, link) {
+ if (strcmp(engine_data->engine_name, engine) == 0) {
+ engine_data->timeslice_set = set;
+ engine_data->timeslice_min = min;
+ engine_data->timeslice_max = max;
+ return true;
+ }
+ }
+ /* If the engine does not exist, create a new entry */
+ engine_data = malloc(sizeof(*engine_data));
+ if (!engine_data)
+ return false;
+
+ engine_data->engine_name = strdup(engine);
+ engine_data->timeslice_set = set;
+ engine_data->timeslice_min = min;
+ engine_data->timeslice_max = max;
+
+ igt_list_add(&engine_data->link, &engines_list);
+ return true;
+}
+
+/**
+ * engines_list_print_all: Print all engines in the list
+ *
+ * Returns: void
+ *
+ */
+static void engines_list_print_all(void)
+{
+ struct engines_timeslice_test_data *engine_data = NULL;
+
+ igt_warn("Engines List:\n");
+ igt_list_for_each_entry(engine_data, &engines_list, link) {
+ igt_warn("Engine: %s, Set: %u, Min: %u, Max: %u\n",
+ engine_data->engine_name,
+ engine_data->timeslice_set,
+ engine_data->timeslice_min,
+ engine_data->timeslice_max);
+ }
+}
+
+/**
+ * engines_list_free_all: Free all engines in the list
+ *
+ * Returns: void
+ *
+ */
+static void engines_list_free_all(void)
+{
+ struct engines_timeslice_test_data *engine_data = NULL, *tmp = NULL;
+
+ igt_list_for_each_entry_safe(engine_data, tmp, &engines_list, link) {
+ free((void *)engine_data->engine_name);
+ free(engine_data);
+ }
+}
+
+/**
+ * debug_info_igt_assert: Print debug information for assertion failures
+ * @msg: message to print
+ * @cond: condition to evaluate
+ */
+static void debug_info_igt_assert(const char *msg, bool cond)
+{
+ if (!cond) {
+ igt_warn("Assertion failed: %s\n", msg);
+ engines_list_print_all();
+ }
+ igt_assert(cond);
+}
+
+/**
+ * get_queue_timeslice_properties: Get the timeslice properties for an engine
+ *
+ * @xe: xe device file descriptor
+ * @engine: engine file descriptor
+ * @set: pointer to store the timeslice duration set for the attacker queue
+ * @min: pointer to store the minimum allowable timeslice duration
+ * @max: pointer to store the maximum allowable timeslice duration
+ *
+ * Returns: 0 on success, -1 on failure
+ */
+static int get_queue_timeslice_properties(int xe, int engine,
+ unsigned int *set, unsigned int *min, unsigned int *max)
+{
+ int defaults;
+
+ defaults = openat(engine, ".defaults", O_DIRECTORY);
+ if (defaults == -1)
+ return -1; /* Failure: Unable to open the defaults directory */
+
+ /* Read the max, min, and set values from the sysfs */
+ if (igt_sysfs_scanf(defaults, "timeslice_duration_max", "%u", max) != 1 ||
+ igt_sysfs_scanf(defaults, "timeslice_duration_min", "%u", min) != 1 ||
+ igt_sysfs_scanf(engine, "timeslice_duration_us", "%u", set) != 1) {
+ close(defaults);
+ return -1; /* Failure: Unable to read sysfs values */
+ }
+ close(defaults);
+
+ return 0; /* Success */
+}
+
+/**
+ * random_u64: Generate a random 64-bit unsigned integer
+ *
+ * Returns: A random 64-bit unsigned integer
+ */
+static uint64_t random_u64(void)
+{
+ uint64_t high = ((uint64_t)rand() << 32);
+ uint64_t low = (uint64_t)rand();
+
+ return high | low;
+}
+
+/**
+ * TEST: Validate the Impact of Timeslice Abuse on Exec Queues
+ * Category: Security
+ * Mega feature: Security Validation Plan
+ * Sub-category: Security Validation Plan
+ * Functionality: Test if exec queue timeslice property can be used as an
+ * attack to prevent other queues from running
+ * Test category: security test
+ *
+ * SUBTEST: get-xe-exec-queue-timeslice-properties
+ * Description: Test to check if timeslice properties are available and
+ * read them.
+ * Test category: functionality test
+ */
+
+/**
+ * get_xe_exec_queue_timeslice_properties:
+ * @xe: xe device file descriptor
+ *
+ * Returns: void
+ */
+static void get_xe_exec_queue_timeslice_properties(int xe)
+{
+ unsigned int max = -1;
+ unsigned int min = -1;
+ unsigned int set = -1;
+ int gt = -1;
+
+ xe_for_each_gt(xe, gt) {
+ int engines = -1;
+ int gt_fd = -1;
+ DIR *dir;
+ struct dirent *de;
+
+ gt_fd = xe_sysfs_gt_open(xe, gt);
+ igt_require(gt_fd != -1);
+
+ engines = openat(gt_fd, "engines", O_RDONLY);
+ igt_require(engines != -1);
+
+ lseek(engines, 0, SEEK_SET);
+
+ dir = fdopendir(engines);
+ if (!dir)
+ close(engines);
+
+ while ((de = readdir(dir))) {
+ int engine_fd = -1;
+
+ if (*de->d_name == '.')
+ continue;
+
+ engine_fd = openat(engines, de->d_name, O_RDONLY);
+ if (engine_fd < 0)
+ continue;
+
+ /* Check if the timeslice properties are available */
+ if (get_queue_timeslice_properties(xe, engine_fd, &set, &min, &max) == 0)
+ engines_list_add_timeslices(de->d_name, set, min, max);
+ else
+ igt_warn("Failed to get timeslice properties\n");
+
+ close(engine_fd);
+ }
+ close(gt_fd);
+ }
+}
+
+/**
+ * xe_exec_queue_test_create_timeslice:
+ * @xe: xe device file descriptor
+ * @vm: vm file descriptor
+ * @timeslice: timeslice value to be set
+ * @expected_ret: expected return value
+ *§
+ * Returns: bool indicating if the queue creation was successful
+ *
+ */
+static bool xe_exec_queue_test_create_timeslice(int xe, int vm,
+ uint64_t timeslice,
+ int expected_ret)
+{
+ uint32_t queue_id = -1;
+ int ret;
+ char error_msg[256];
+
+ struct drm_xe_engine_class_instance instance = {
+ .engine_class = DRM_XE_ENGINE_CLASS_VM_BIND,
+ };
+ struct drm_xe_ext_set_property property = {
+ .base.name = DRM_XE_EXEC_QUEUE_EXTENSION_SET_PROPERTY,
+ .base.next_extension = 0,
+ .property = DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE,
+ .value = timeslice,
+ };
+
+ igt_assert(vm != -1);
+
+ ret = __xe_exec_queue_create(xe, vm, 1, 1,
+ &instance, to_user_pointer(&property),
+ &queue_id);
+ if (ret == 0)
+ xe_exec_queue_destroy(xe, queue_id);
+
+ if (ret == expected_ret)
+ return true;
+
+ snprintf(error_msg, sizeof(error_msg),
+ "ERROR: Failed to create exec queue with timeslice %lu, expected %d, got %d",
+ timeslice, expected_ret, ret);
+ debug_info_igt_assert(error_msg, ret == expected_ret);
+
+ return false;
+}
+
+/**
+ * xe_exec_queue_test_iterate_create_timeslice:
+ * @xe: xe device file descriptor
+ * @vm: vm file descriptor
+ * @test_case: struct containing the timeslice value and expected result
+ * @test_case_count: number of test cases
+ *
+ * Returns: void
+ *
+ */
+static void xe_exec_queue_test_iterate_create_timeslice(int xe, int vm,
+ struct timeslice_test_case *test_case,
+ int test_case_count)
+{
+ for (int i = 0; i < test_case_count; i++)
+ xe_exec_queue_test_create_timeslice(xe, vm,
+ test_case[i].value,
+ test_case[i].expected_result);
+}
+
+/**
+ * SUBTEST: xe-exec-queue-timeslice-boundary-value-analysis
+ * Description: Test to check if the timeslice boundary values are
+ * working as expected.
+ * Test category: functionality test
+ */
+
+/**
+ * xe_exec_queue_timeslice_boundary_value_analysis:
+ * @xe: xe device file descriptor
+ * @vm: vm file descriptor
+ *
+ * Returns: void
+ *
+ */
+static void xe_exec_queue_timeslice_boundary_value_analysis(int xe, int vm)
+{
+ struct engines_timeslice_test_data *engine_data = NULL;
+ int test_case_count = 6;
+ struct timeslice_test_case test_cases[test_case_count];
+
+ igt_list_for_each_entry(engine_data, &engines_list, link) {
+ if (engine_data->timeslice_set != -1)
+ break;
+ }
+ igt_assert(engine_data != NULL);
+ igt_assert(engine_data->timeslice_set != -1);
+
+ /* Test cases for boundary value analysis */
+ test_cases[0].value = engine_data->timeslice_max + 1;
+ test_cases[0].expected_result = -EINVAL;
+ test_cases[1].value = engine_data->timeslice_max;
+ test_cases[1].expected_result = 0;
+ test_cases[2].value = engine_data->timeslice_max - 1;
+ test_cases[2].expected_result = 0;
+ test_cases[3].value = engine_data->timeslice_min - 1;
+ test_cases[3].expected_result = -EINVAL;
+ test_cases[4].value = engine_data->timeslice_min;
+ test_cases[4].expected_result = 0;
+ test_cases[5].value = engine_data->timeslice_min + 1;
+ test_cases[5].expected_result = 0;
+
+ /* Check if the timeslice values are working as expected */
+ xe_exec_queue_test_iterate_create_timeslice(xe, vm, test_cases,
+ test_case_count);
+}
+
+/**
+ * SUBTEST: xe-exec-queue-timeslice-equivalence-partitioning
+ * Description: Divide timeslice values into partitions where all values should
+ * have the same behavior. This test checks if the timeslice
+ * values are working as expected.
+ *
+ * Test category: functionality test
+ */
+
+/**
+ * xe_exec_queue_timeslice_equivalence_partitioning:
+ * @xe: xe device file descriptor
+ * @vm: vm file descriptor
+ *
+ * Returns: void
+ *
+ */
+static void xe_exec_queue_timeslice_equivalence_partitioning(int xe, int vm)
+{
+ struct engines_timeslice_test_data *engine_data = NULL;
+ int test_case_count = 5;
+ struct timeslice_test_case test_cases[test_case_count];
+
+ igt_list_for_each_entry(engine_data, &engines_list, link) {
+ if (engine_data->timeslice_set != -1)
+ break;
+ }
+ igt_assert(engine_data != NULL);
+ igt_assert(engine_data->timeslice_set != -1);
+
+ /* Test cases for equivalence partitioning */
+ test_cases[0].value = engine_data->timeslice_min - 1;
+ test_cases[0].expected_result = -EINVAL;
+ test_cases[1].value = engine_data->timeslice_min;
+ test_cases[1].expected_result = 0;
+ test_cases[2].value = (engine_data->timeslice_min + engine_data->timeslice_max) / 2;
+ test_cases[2].expected_result = 0;
+ test_cases[3].value = engine_data->timeslice_max;
+ test_cases[3].expected_result = 0;
+ test_cases[4].value = engine_data->timeslice_max + 1;
+ test_cases[4].expected_result = -EINVAL;
+
+ /* Check if the timeslice values are working as expected */
+ xe_exec_queue_test_iterate_create_timeslice(xe, vm, test_cases,
+ test_case_count);
+}
+
+/**
+ * SUBTEST: xe-exec-queue-timeslice-fuzzing
+ * Description: Test a large set of random timeslice values to check if the
+ * behavior is as expected. Includes testing for:
+ * - very large numbers
+ * - empty value
+ * - null value
+ *
+ * Test category: functionality test
+ */
+
+/**
+ * xe_exec_queue_timeslice_fuzzing:
+ * @xe: xe device file descriptor
+ * @random_count: number of random timeslice values to test
+ *
+ * Returns: void
+ *
+ */
+static void xe_exec_queue_timeslice_fuzzing(int xe, int vm, int random_count)
+{
+ struct engines_timeslice_test_data *engine_data = NULL;
+ __u64 timeslice_value;
+ uint32_t queue_id = -1;
+
+ struct drm_xe_engine_class_instance instance = {
+ .engine_class = DRM_XE_ENGINE_CLASS_VM_BIND,
+ };
+ struct drm_xe_ext_set_property empty_value_property = {
+ .base.name = DRM_XE_EXEC_QUEUE_EXTENSION_SET_PROPERTY,
+ .base.next_extension = 0,
+ .property = DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE,
+ };
+
+ igt_list_for_each_entry(engine_data, &engines_list, link) {
+ if (engine_data->timeslice_set != -1)
+ break;
+ }
+ igt_assert(engine_data != NULL);
+ igt_assert(engine_data->timeslice_set != -1);
+
+ igt_assert(vm != -1);
+
+ /* test empty timeslice_value 10 times*/
+ for (int i = 0; i < 10; i++)
+ igt_assert_eq(__xe_exec_queue_create(xe, vm, 1, 1, &instance,
+ to_user_pointer(&empty_value_property),
+ &queue_id), -EINVAL);
+
+ /* Very large number 10 times for max_u64 and for max_u64 -1 */
+ timeslice_value = MAX_U64;
+ for (int i = 0; i < 10; i++)
+ xe_exec_queue_test_create_timeslice(xe, vm, timeslice_value,
+ -EINVAL);
+ timeslice_value = MAX_U64 - 1;
+ for (int i = 0; i < 10; i++)
+ xe_exec_queue_test_create_timeslice(xe, vm, timeslice_value,
+ -EINVAL);
+
+ /* Test '\0' timeslice_value 10 times */
+ for (int i = 0; i < 10; i++)
+ xe_exec_queue_test_create_timeslice(xe, vm, '\0', -EINVAL);
+
+ /* Test random_count random values */
+ srand((unsigned int)time(NULL));
+
+ for (int i = 0; i < random_count; i++) {
+ timeslice_value = random_u64();
+
+ if (timeslice_value < engine_data->timeslice_min ||
+ timeslice_value > engine_data->timeslice_max)
+ xe_exec_queue_test_create_timeslice(xe, vm,
+ timeslice_value,
+ -EINVAL);
+ else
+ xe_exec_queue_test_create_timeslice(xe, vm,
+ timeslice_value,
+ 0);
+ }
+}
+
+/**
+ * SUBTEST: xe-exec-queue-timeslice-fuzzing-stress-test
+ * Description: Test a large set of random timeslice values to check if the
+ * behavior is as expected. Includes testing for:
+ * - very large numbers
+ * - empty value
+ * - null value
+ *
+ * Test category: functionality test
+ */
+
+ /**
+ * fuzz_workload: Thread function to perform fuzz testing
+ * @args: thread arguments containing the xe device file descriptor and
+ * random count
+ *
+ * Returns: void
+ */
+static void *fuzz_workload(void *args)
+{
+ thread_args_t *thread_args = (thread_args_t *) args;
+
+ /* Call the fuzz testing function with the provided arguments */
+ xe_exec_queue_timeslice_fuzzing(thread_args->xe, thread_args->vm,
+ thread_args->random_count);
+
+ return NULL;
+}
+
+/**
+ * xe_exec_queue_timeslice_fuzzing_stress_threads:
+ * @xe: xe device file descriptor
+ * @vm: vm file descriptor
+ * @thread_count: number of threads to create
+ * @random_count_per_thread: number of random timeslice values per thread
+ *
+ * Returns: void
+ *
+ */
+static void xe_exec_queue_timeslice_fuzzing_stress_threads(int xe,
+ int vm,
+ int thread_count,
+ int random_count_per_thread)
+{
+ pthread_t *threads;
+ thread_args_t *thread_args;
+
+ threads = malloc(thread_count * sizeof(pthread_t));
+ igt_assert(threads);
+ thread_args = malloc(thread_count * sizeof(thread_args_t));
+ igt_assert(thread_args);
+
+ igt_info("Starting stress test with %d threads and with %d random tests each...\n",
+ thread_count, random_count_per_thread);
+
+ // Create the specified number of threads
+ for (int i = 0; i < thread_count; i++) {
+ thread_args[i].xe = xe;
+ thread_args[i].vm = vm;
+ thread_args[i].random_count = random_count_per_thread;
+
+ if (pthread_create(&threads[i], NULL, fuzz_workload, &thread_args[i]) != 0) {
+ igt_info("Failed to create thread %d.\n", i);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ // Wait for all threads to finish
+ for (int i = 0; i < thread_count; i++) {
+ if (pthread_join(threads[i], NULL) != 0)
+ igt_info("Failed to join thread %d.\n", i);
+ }
+
+ igt_info("Stress test with %d threads completed successfully.\n",
+ thread_count);
+
+ // Free allocated memory
+ free(threads);
+ free(thread_args);
+}
+
+igt_main
+{
+ bool has_sysfs = false;
+ int sys_fd = -1;
+ int xe = -1;
+ int vm = -1;
+
+ igt_fixture {
+ /* Disable logging for this igt: Logging imposes a 20X slowdown
+ * on the operations we are trying to stress test. The logging
+ * slows down and serializes the operations, which is not what
+ * we want. igt_drm_debug_level_update() installs an exit
+ * handler making sure that the logging is reset to the previous
+ * value when the test ends.
+ */
+ igt_drm_debug_level_update(0);
+
+ /* Initialize the list of engines */
+ IGT_INIT_LIST_HEAD(&engines_list);
+
+ xe = drm_open_driver(DRIVER_XE);
+ sys_fd = igt_sysfs_open(xe);
+
+ if (sys_fd != -1) {
+ close(sys_fd);
+ has_sysfs = true;
+ } else {
+ has_sysfs = false;
+ }
+ }
+
+ igt_subtest("get-xe-exec-queue-timeslice-properties") {
+ igt_require(has_sysfs);
+ get_xe_exec_queue_timeslice_properties(xe);
+ }
+
+ igt_fixture {
+ vm = xe_vm_create(xe, 0, 0);
+ igt_assert(vm != -1);
+ }
+
+ igt_subtest("xe-exec-queue-timeslice-boundary-value-analysis") {
+ xe_exec_queue_timeslice_boundary_value_analysis(xe, vm);
+ }
+
+ igt_subtest("xe-exec-queue-timeslice-equivalence-partitioning") {
+ xe_exec_queue_timeslice_equivalence_partitioning(xe, vm);
+ }
+
+ igt_subtest("xe-exec-queue-timeslice-fuzzing") {
+ xe_exec_queue_timeslice_fuzzing(xe, vm, 1000000);
+ }
+
+ igt_subtest("xe-exec-queue-timeslice-fuzzing-stress-test") {
+ xe_exec_queue_timeslice_fuzzing_stress_threads(xe, vm,
+ 50000, 500);
+ }
+
+ igt_fixture {
+ engines_list_free_all();
+ close(sys_fd);
+
+ if (vm != -1)
+ xe_vm_destroy(xe, vm);
+
+ xe_device_put(xe);
+ drm_close_driver(xe);
+ }
+}
diff --git a/tests/meson.build b/tests/meson.build
index 20ddddb89..560b74ceb 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -273,6 +273,7 @@ intel_kms_progs = [
]
intel_xe_progs = [
+ 'sec_xe_exec_queue_timeslice_abuse',
'xe_wedged',
'xe_ccs',
'xe_create',
--
2.43.0
More information about the igt-dev
mailing list