drm/xe: add migrate ULLS period configfs attribute

Add a configfs attribute to control the migrate ULLS period.
 
The migrate ULLS period specifies how long, in milliseconds, migrate
ULLS remains active before exiting. Migrate ULLS is currently used by
page-fault handling and SVM prefetch operations to process migration
work through a continuously running batch.
 
The attribute defaults to 5 ms. Setting the value to 0 disables ULLS.
 
This knob is primarily intended for performance tuning and evaluation,
allowing experimentation with the trade-off between reducing ULLS
startup/teardown overhead and limiting the time spent in a continuously
running migration workload.

Signed-off-by: Matthew Brost <matthew.brost@intel.com>
Reviewed-by: Maarten Lankhorst <dev@lankhorst.se>
Link: https://patch.msgid.link/20260925201526.1355279-24-matthew.brost@intel.com
This commit is contained in:
Matthew Brost 2026-09-25 13:15:25 -07:00
parent 085d8f468f
commit cb85dddfee
3 changed files with 82 additions and 6 deletions

View File

@ -61,6 +61,7 @@
* ├── survivability_mode
* ├── gt_types_allowed
* ├── engines_allowed
* ├── migrate_ulls_period_ms
* ├── enable_psmi
* └── disable_vram_page_offline
*
@ -262,6 +263,20 @@
*
* This attribute can only be set before binding to the device.
*
* Migrate ULLS Period (ms)
* ------------------------
*
* Migrate ULLS period, in milliseconds. This is the delay between entering
* migrate ULLS (a continuously running batch) and exiting it. Migrate ULLS is
* currently entered during page faults and SVM prefetch operations. Default 5,
* zero indicates ULLS is disabled.
*
* How to disable migration ULLS:
*
* # echo 0 > /sys/kernel/config/xe/0000:03:00.0/migrate_ulls_period_ms
*
* This attribute can only be set before binding to the device.
*
* Remove devices
* ==============
*
@ -283,6 +298,7 @@ struct xe_config_group_device {
struct xe_config_device {
u64 gt_types_allowed;
u64 engines_allowed;
u32 migrate_ulls_period_ms;
struct wa_bb ctx_restore_post_bb[XE_ENGINE_CLASS_MAX];
struct wa_bb ctx_restore_mid_bb[XE_ENGINE_CLASS_MAX];
bool survivability_mode;
@ -306,6 +322,7 @@ struct xe_config_group_device {
static const struct xe_config_device device_defaults = {
.gt_types_allowed = U64_MAX,
.engines_allowed = U64_MAX,
.migrate_ulls_period_ms = 5,
.survivability_mode = false,
.enable_psmi = false,
.enable_multi_queue = true,
@ -631,6 +648,33 @@ static ssize_t enable_multi_queue_store(struct config_item *item, const char *pa
return len;
}
static ssize_t migrate_ulls_period_ms_show(struct config_item *item, char *page)
{
struct xe_config_device *dev = to_xe_config_device(item);
return sprintf(page, "%u\n", dev->migrate_ulls_period_ms);
}
static ssize_t migrate_ulls_period_ms_store(struct config_item *item,
const char *page, size_t len)
{
struct xe_config_group_device *dev = to_xe_config_group_device(item);
u32 val;
int ret;
ret = kstrtou32(page, 0, &val);
if (ret)
return ret;
guard(mutex)(&dev->lock);
if (is_bound(dev))
return -EBUSY;
dev->config.migrate_ulls_period_ms = val;
return len;
}
static ssize_t disable_vram_page_offline_show(struct config_item *item, char *page)
{
struct xe_config_device *dev = to_xe_config_device(item);
@ -896,6 +940,7 @@ static ssize_t ctx_restore_post_bb_store(struct config_item *item,
CONFIGFS_ATTR(, ctx_restore_mid_bb);
CONFIGFS_ATTR(, ctx_restore_post_bb);
CONFIGFS_ATTR(, enable_multi_queue);
CONFIGFS_ATTR(, migrate_ulls_period_ms);
CONFIGFS_ATTR(, enable_psmi);
CONFIGFS_ATTR(, disable_vram_page_offline);
CONFIGFS_ATTR(, engines_allowed);
@ -906,6 +951,7 @@ static struct configfs_attribute *xe_config_device_attrs[] = {
&attr_ctx_restore_mid_bb,
&attr_ctx_restore_post_bb,
&attr_enable_multi_queue,
&attr_migrate_ulls_period_ms,
&attr_enable_psmi,
&attr_disable_vram_page_offline,
&attr_engines_allowed,
@ -1189,6 +1235,7 @@ static void dump_custom_dev_config(struct pci_dev *pdev,
PRI_CUSTOM_ATTR("%llx", gt_types_allowed);
PRI_CUSTOM_ATTR("%llx", engines_allowed);
PRI_CUSTOM_ATTR("%u", migrate_ulls_period_ms);
PRI_CUSTOM_ATTR("%d", enable_multi_queue);
PRI_CUSTOM_ATTR("%d", enable_psmi);
PRI_CUSTOM_ATTR("%d", disable_vram_page_offline);
@ -1340,6 +1387,26 @@ bool xe_configfs_get_enable_multi_queue(struct pci_dev *pdev)
return ret;
}
/**
* xe_configfs_get_migrate_ulls_period_ms - get configfs migrate_ulls_period_ms setting
* @pdev: pci device
*
* Return: Migrate ULLS period in milliseconds (zero is disabled).
*/
u32 xe_configfs_get_migrate_ulls_period_ms(struct pci_dev *pdev)
{
struct xe_config_group_device *dev = find_xe_config_group_device(pdev);
u32 ret;
if (!dev)
return device_defaults.migrate_ulls_period_ms;
ret = dev->config.migrate_ulls_period_ms;
config_group_put(&dev->group);
return ret;
}
/**
* xe_configfs_get_disable_vram_page_offline - get configfs disable_vram_page_offline setting
* @pdev: pci device

View File

@ -24,6 +24,7 @@ bool xe_configfs_media_gt_allowed(struct pci_dev *pdev);
u64 xe_configfs_get_engines_allowed(struct pci_dev *pdev);
bool xe_configfs_get_psmi_enabled(struct pci_dev *pdev);
bool xe_configfs_get_enable_multi_queue(struct pci_dev *pdev);
u32 xe_configfs_get_migrate_ulls_period_ms(struct pci_dev *pdev);
bool xe_configfs_get_disable_vram_page_offline(struct pci_dev *pdev);
u32 xe_configfs_get_ctx_restore_mid_bb(struct pci_dev *pdev,
enum xe_engine_class class,
@ -45,6 +46,7 @@ static inline bool xe_configfs_media_gt_allowed(struct pci_dev *pdev) { return t
static inline u64 xe_configfs_get_engines_allowed(struct pci_dev *pdev) { return U64_MAX; }
static inline bool xe_configfs_get_psmi_enabled(struct pci_dev *pdev) { return false; }
static inline bool xe_configfs_get_enable_multi_queue(struct pci_dev *pdev) { return true; }
static inline u32 xe_configfs_get_migrate_ulls_period_ms(struct pci_dev *pdev) { return 5; }
static inline bool xe_configfs_get_disable_vram_page_offline(struct pci_dev *pdev) { return false; }
static inline u32 xe_configfs_get_ctx_restore_mid_bb(struct pci_dev *pdev,
enum xe_engine_class class,

View File

@ -23,6 +23,7 @@
#include "xe_assert.h"
#include "xe_bb.h"
#include "xe_bo.h"
#include "xe_configfs.h"
#include "xe_exec_queue.h"
#include "xe_ggtt.h"
#include "xe_gt.h"
@ -81,14 +82,17 @@ struct xe_migrate {
u64 min_chunk_size;
/** @ulls: ULLS support */
struct {
/** @ulls.exit_ms: ULLS exit period milliseconds */
u32 exit_ms;
/** @ulls.enabled: ULLS is enabled, protected by job_mutex */
bool enabled;
#define ULLS_EXIT_JIFFIES msecs_to_jiffies(5)
/** @ulls.exit_work: ULLS exit worker */
struct delayed_work exit_work;
} ulls;
};
#define ULLS_EXIT_JIFFIES(_m) msecs_to_jiffies((_m)->ulls.exit_ms)
#define MAX_PREEMPTDISABLE_TRANSFER SZ_8M /* Around 1ms. */
#define MAX_CCS_LIMITED_TRANSFER SZ_4M /* XE_PAGE_SIZE * (FIELD_MAX(XE2_CCS_SIZE_MASK) + 1) */
#define NUM_PT_SLOTS 48
@ -512,7 +516,7 @@ static struct dma_fence *xe_migrate_job_push(struct xe_migrate *m,
if (xe_migrate_ulls_enabled(m)) {
ulls = ULLS_ACTIVE;
mod_delayed_work(system_percpu_wq, &m->ulls.exit_work,
ULLS_EXIT_JIFFIES);
ULLS_EXIT_JIFFIES(m));
}
return __xe_migrate_job_push(m, job, ulls);
@ -534,7 +538,7 @@ void xe_migrate_ulls_enter(struct xe_migrate *m)
xe_assert(xe, xe->info.has_usm);
if (!IS_DGFX(xe))
if (!IS_DGFX(xe) || !m->ulls.exit_ms)
return;
job_alloc:
@ -572,7 +576,7 @@ void xe_migrate_ulls_enter(struct xe_migrate *m)
xe_sched_job_put(job);
if (xe_migrate_ulls_enabled(m))
mod_delayed_work(system_percpu_wq, &m->ulls.exit_work,
ULLS_EXIT_JIFFIES);
ULLS_EXIT_JIFFIES(m));
mutex_unlock(&m->job_mutex);
}
@ -599,7 +603,7 @@ static void xe_migrate_ulls_exit(struct work_struct *work)
if (WARN_ON_ONCE(IS_ERR(job))) {
drm_dev_exit(idx);
mod_delayed_work(system_percpu_wq, &m->ulls.exit_work,
ULLS_EXIT_JIFFIES);
ULLS_EXIT_JIFFIES(m));
return; /* Not fatal */
}
@ -616,7 +620,7 @@ static void xe_migrate_ulls_exit(struct work_struct *work)
} else {
xe_sched_job_put(job);
mod_delayed_work(system_percpu_wq, &m->ulls.exit_work,
ULLS_EXIT_JIFFIES);
ULLS_EXIT_JIFFIES(m));
}
}
@ -700,6 +704,9 @@ int xe_migrate_init(struct xe_migrate *m)
(unsigned long long)m->min_chunk_size);
}
m->ulls.exit_ms =
xe_configfs_get_migrate_ulls_period_ms(to_pci_dev(xe->drm.dev));
return err;
err_out: