drivers/gpu/drm/xe/xe_svm.c
Source file repositories/reference/linux-study-clean/drivers/gpu/drm/xe/xe_svm.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/gpu/drm/xe/xe_svm.c- Extension
.c- Size
- 56492 bytes
- Lines
- 2050
- Domain
- Driver Families
- Bucket
- drivers/gpu
- Inferred role
- Driver Families: implementation source
- Status
- source implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/pci-p2pdma.hdrm/drm_drv.hdrm/drm_managed.hdrm/drm_pagemap.hdrm/drm_pagemap_util.hxe_bo.hxe_exec_queue_types.hxe_gt_stats.hxe_migrate.hxe_module.hxe_pm.hxe_pt.hxe_svm.hxe_tile.hxe_tlb_inval.hxe_ttm_vram_mgr.hxe_vm.hxe_vm_types.hxe_vram_types.h
Detected Declarations
enum xe_svm_copy_dirfunction xe_svm_range_in_vramfunction xe_svm_range_has_vram_bindingfunction xe_svm_range_in_vramfunction xe_svm_range_allocfunction xe_svm_range_freefunction xe_svm_garbage_collector_add_rangefunction xe_svm_tlb_inval_count_stats_incrfunction xe_svm_range_notifier_event_beginfunction xe_svm_range_notifier_event_endfunction xe_svm_tlb_inval_us_stats_incrfunction xe_svm_invalidatefunction __xe_svm_garbage_collectorfunction xe_vma_set_default_attributesfunction xe_svm_range_set_default_attrfunction xe_svm_garbage_collectorfunction xe_svm_garbage_collector_work_funcfunction xe_page_to_dpafunction xe_page_to_pciefunction xe_svm_copy_kb_stats_incrfunction xe_svm_copy_us_stats_incrfunction xe_svm_copyfunction xe_svm_copy_to_devmemfunction xe_svm_copy_to_ramfunction xe_svm_devmem_releasefunction block_offset_to_pfnfunction xe_svm_populate_devmem_pfnfunction list_for_each_entryfunction xe_svm_get_pagemapsfunction xe_pagemap_putfunction xe_svm_put_pagemapsfunction for_each_tilefunction xe_has_interconnectfunction xe_svm_initfunction xe_svm_closefunction xe_svm_finifunction xe_svm_range_has_pagemap_lockedfunction xe_svm_range_has_pagemapfunction xe_svm_range_is_validfunction xe_svm_range_migrate_to_smemfunction xe_svm_range_validatefunction xe_svm_find_vma_startfunction xe_drm_pagemap_populate_mmfunction xe_validation_guardfunction supports_4K_migrationfunction xe_svm_range_needs_migrate_to_vramfunction __xe_svm_handle_pagefaultfunction xe_svm_handle_pagefault
Annotated Snippet
if (xe_pt_zap_ptes_range(tile, vm, range)) {
/*
* WRITE_ONCE pairs with READ_ONCE in
* xe_vm_has_valid_gpu_mapping()
*/
WRITE_ONCE(range->tile_invalidated,
range->tile_invalidated | BIT(id));
if (!(tile_mask & BIT(id))) {
xe_svm_tlb_inval_count_stats_incr(tile->primary_gt);
if (tile->media_gt)
xe_svm_tlb_inval_count_stats_incr(tile->media_gt);
tile_mask |= BIT(id);
}
}
return tile_mask;
}
static void
xe_svm_range_notifier_event_end(struct xe_vm *vm, struct drm_gpusvm_range *r,
const struct mmu_notifier_range *mmu_range)
{
struct drm_gpusvm_ctx ctx = { .in_notifier = true, };
xe_svm_assert_in_notifier(vm);
drm_gpusvm_range_unmap_pages(&vm->svm.gpusvm, r, &ctx);
if (!xe_vm_is_closed(vm) && mmu_range->event == MMU_NOTIFY_UNMAP)
xe_svm_garbage_collector_add_range(vm, to_xe_range(r),
mmu_range);
}
static void xe_svm_tlb_inval_us_stats_incr(struct xe_gt *gt, ktime_t start)
{
s64 us_delta = xe_gt_stats_ktime_us_delta(start);
xe_gt_stats_incr(gt, XE_GT_STATS_ID_SVM_TLB_INVAL_US, us_delta);
}
static void xe_svm_invalidate(struct drm_gpusvm *gpusvm,
struct drm_gpusvm_notifier *notifier,
const struct mmu_notifier_range *mmu_range)
{
struct xe_vm *vm = gpusvm_to_vm(gpusvm);
struct xe_tlb_inval_batch batch;
struct xe_device *xe = vm->xe;
struct drm_gpusvm_range *r, *first;
struct xe_tile *tile;
ktime_t start = xe_gt_stats_ktime_get();
u64 adj_start = mmu_range->start, adj_end = mmu_range->end;
u8 tile_mask = 0, id;
long err;
xe_svm_assert_in_notifier(vm);
vm_dbg(&gpusvm_to_vm(gpusvm)->xe->drm,
"INVALIDATE: asid=%u, gpusvm=%p, seqno=%lu, start=0x%016lx, end=0x%016lx, event=%d",
vm->usm.asid, gpusvm, notifier->notifier.invalidate_seq,
mmu_range->start, mmu_range->end, mmu_range->event);
/* Adjust invalidation to notifier boundaries */
adj_start = max(drm_gpusvm_notifier_start(notifier), adj_start);
adj_end = min(drm_gpusvm_notifier_end(notifier), adj_end);
first = drm_gpusvm_range_find(notifier, adj_start, adj_end);
if (!first)
return;
/*
* PTs may be getting destroyed so not safe to touch these but PT should
* be invalidated at this point in time. Regardless we still need to
* ensure any dma mappings are unmapped in the here.
*/
if (xe_vm_is_closed(vm))
goto range_notifier_event_end;
/*
* XXX: Less than ideal to always wait on VM's resv slots if an
* invalidation is not required. Could walk range list twice to figure
* out if an invalidations is need, but also not ideal.
*/
err = dma_resv_wait_timeout(xe_vm_resv(vm),
DMA_RESV_USAGE_BOOKKEEP,
false, MAX_SCHEDULE_TIMEOUT);
XE_WARN_ON(err <= 0);
r = first;
drm_gpusvm_for_each_range(r, notifier, adj_start, adj_end)
tile_mask |= xe_svm_range_notifier_event_begin(vm, r, mmu_range,
Annotation
- Immediate include surface: `linux/pci-p2pdma.h`, `drm/drm_drv.h`, `drm/drm_managed.h`, `drm/drm_pagemap.h`, `drm/drm_pagemap_util.h`, `xe_bo.h`, `xe_exec_queue_types.h`, `xe_gt_stats.h`.
- Detected declarations: `enum xe_svm_copy_dir`, `function xe_svm_range_in_vram`, `function xe_svm_range_has_vram_binding`, `function xe_svm_range_in_vram`, `function xe_svm_range_alloc`, `function xe_svm_range_free`, `function xe_svm_garbage_collector_add_range`, `function xe_svm_tlb_inval_count_stats_incr`, `function xe_svm_range_notifier_event_begin`, `function xe_svm_range_notifier_event_end`.
- Atlas domain: Driver Families / drivers/gpu.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.