drm/amdkfd: invalidate tables on page retry fault
GPU page tables are invalidated by unmapping prange directly at the mmu notifier, when page fault retry is enabled through amdgpu_noretry global parameter. The restore page table is performed at the page fault handler. If xnack is on, we update GPU mappings after migration to avoid unnecessary GPUVM faults. Signed-off-by: Alex Sierra <alex.sierra@amd.com> Signed-off-by: Philip Yang <Philip.Yang@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
48ff079b28
commit
90d7d3eda5
3 changed files with 70 additions and 17 deletions
|
@ -808,7 +808,11 @@ static vm_fault_t svm_migrate_to_ram(struct vm_fault *vmf)
|
||||||
pr_debug("failed %d migrate 0x%p [0x%lx 0x%lx] to ram\n", r,
|
pr_debug("failed %d migrate 0x%p [0x%lx 0x%lx] to ram\n", r,
|
||||||
prange, prange->start, prange->last);
|
prange, prange->start, prange->last);
|
||||||
|
|
||||||
op = SVM_OP_UPDATE_RANGE_NOTIFIER;
|
/* xnack on, update mapping on GPUs with ACCESS_IN_PLACE */
|
||||||
|
if (p->xnack_enabled && parent == prange)
|
||||||
|
op = SVM_OP_UPDATE_RANGE_NOTIFIER_AND_MAP;
|
||||||
|
else
|
||||||
|
op = SVM_OP_UPDATE_RANGE_NOTIFIER;
|
||||||
svm_range_add_list_work(&p->svms, parent, mm, op);
|
svm_range_add_list_work(&p->svms, parent, mm, op);
|
||||||
schedule_deferred_list_work(&p->svms);
|
schedule_deferred_list_work(&p->svms);
|
||||||
|
|
||||||
|
|
|
@ -912,6 +912,13 @@ svm_range_split_by_granularity(struct kfd_process *p, struct mm_struct *mm,
|
||||||
svm_range_add_child(parent, mm, tail, SVM_OP_ADD_RANGE);
|
svm_range_add_child(parent, mm, tail, SVM_OP_ADD_RANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* xnack on, update mapping on GPUs with ACCESS_IN_PLACE */
|
||||||
|
if (p->xnack_enabled && prange->work_item.op == SVM_OP_ADD_RANGE) {
|
||||||
|
prange->work_item.op = SVM_OP_ADD_RANGE_AND_MAP;
|
||||||
|
pr_debug("change prange 0x%p [0x%lx 0x%lx] op %d\n",
|
||||||
|
prange, prange->start, prange->last,
|
||||||
|
SVM_OP_ADD_RANGE_AND_MAP);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1452,25 +1459,52 @@ svm_range_evict(struct svm_range *prange, struct mm_struct *mm,
|
||||||
unsigned long start, unsigned long last)
|
unsigned long start, unsigned long last)
|
||||||
{
|
{
|
||||||
struct svm_range_list *svms = prange->svms;
|
struct svm_range_list *svms = prange->svms;
|
||||||
int evicted_ranges;
|
struct kfd_process *p;
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
atomic_inc(&prange->invalid);
|
p = container_of(svms, struct kfd_process, svms);
|
||||||
evicted_ranges = atomic_inc_return(&svms->evicted_ranges);
|
|
||||||
if (evicted_ranges != 1)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
pr_debug("evicting svms 0x%p range [0x%lx 0x%lx]\n",
|
pr_debug("invalidate svms 0x%p prange [0x%lx 0x%lx] [0x%lx 0x%lx]\n",
|
||||||
prange->svms, prange->start, prange->last);
|
svms, prange->start, prange->last, start, last);
|
||||||
|
|
||||||
/* First eviction, stop the queues */
|
if (!p->xnack_enabled) {
|
||||||
r = kgd2kfd_quiesce_mm(mm);
|
int evicted_ranges;
|
||||||
if (r)
|
|
||||||
pr_debug("failed to quiesce KFD\n");
|
|
||||||
|
|
||||||
pr_debug("schedule to restore svm %p ranges\n", svms);
|
atomic_inc(&prange->invalid);
|
||||||
schedule_delayed_work(&svms->restore_work,
|
evicted_ranges = atomic_inc_return(&svms->evicted_ranges);
|
||||||
msecs_to_jiffies(AMDGPU_SVM_RANGE_RESTORE_DELAY_MS));
|
if (evicted_ranges != 1)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
pr_debug("evicting svms 0x%p range [0x%lx 0x%lx]\n",
|
||||||
|
prange->svms, prange->start, prange->last);
|
||||||
|
|
||||||
|
/* First eviction, stop the queues */
|
||||||
|
r = kgd2kfd_quiesce_mm(mm);
|
||||||
|
if (r)
|
||||||
|
pr_debug("failed to quiesce KFD\n");
|
||||||
|
|
||||||
|
pr_debug("schedule to restore svm %p ranges\n", svms);
|
||||||
|
schedule_delayed_work(&svms->restore_work,
|
||||||
|
msecs_to_jiffies(AMDGPU_SVM_RANGE_RESTORE_DELAY_MS));
|
||||||
|
} else {
|
||||||
|
struct svm_range *pchild;
|
||||||
|
unsigned long s, l;
|
||||||
|
|
||||||
|
pr_debug("invalidate unmap svms 0x%p [0x%lx 0x%lx] from GPUs\n",
|
||||||
|
prange->svms, start, last);
|
||||||
|
list_for_each_entry(pchild, &prange->child_list, child_list) {
|
||||||
|
mutex_lock_nested(&pchild->lock, 1);
|
||||||
|
s = max(start, pchild->start);
|
||||||
|
l = min(last, pchild->last);
|
||||||
|
if (l >= s)
|
||||||
|
svm_range_unmap_from_gpus(pchild, s, l);
|
||||||
|
mutex_unlock(&pchild->lock);
|
||||||
|
}
|
||||||
|
s = max(start, prange->start);
|
||||||
|
l = min(last, prange->last);
|
||||||
|
if (l >= s)
|
||||||
|
svm_range_unmap_from_gpus(prange, s, l);
|
||||||
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -1673,12 +1707,25 @@ svm_range_handle_list_op(struct svm_range_list *svms, struct svm_range *prange)
|
||||||
svms, prange, prange->start, prange->last);
|
svms, prange, prange->start, prange->last);
|
||||||
svm_range_update_notifier_and_interval_tree(mm, prange);
|
svm_range_update_notifier_and_interval_tree(mm, prange);
|
||||||
break;
|
break;
|
||||||
|
case SVM_OP_UPDATE_RANGE_NOTIFIER_AND_MAP:
|
||||||
|
pr_debug("update and map 0x%p prange 0x%p [0x%lx 0x%lx]\n",
|
||||||
|
svms, prange, prange->start, prange->last);
|
||||||
|
svm_range_update_notifier_and_interval_tree(mm, prange);
|
||||||
|
/* TODO: implement deferred validation and mapping */
|
||||||
|
break;
|
||||||
case SVM_OP_ADD_RANGE:
|
case SVM_OP_ADD_RANGE:
|
||||||
pr_debug("add 0x%p prange 0x%p [0x%lx 0x%lx]\n", svms, prange,
|
pr_debug("add 0x%p prange 0x%p [0x%lx 0x%lx]\n", svms, prange,
|
||||||
prange->start, prange->last);
|
prange->start, prange->last);
|
||||||
svm_range_add_to_svms(prange);
|
svm_range_add_to_svms(prange);
|
||||||
svm_range_add_notifier_locked(mm, prange);
|
svm_range_add_notifier_locked(mm, prange);
|
||||||
break;
|
break;
|
||||||
|
case SVM_OP_ADD_RANGE_AND_MAP:
|
||||||
|
pr_debug("add and map 0x%p prange 0x%p [0x%lx 0x%lx]\n", svms,
|
||||||
|
prange, prange->start, prange->last);
|
||||||
|
svm_range_add_to_svms(prange);
|
||||||
|
svm_range_add_notifier_locked(mm, prange);
|
||||||
|
/* TODO: implement deferred validation and mapping */
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
WARN_ONCE(1, "Unknown prange 0x%p work op %d\n", prange,
|
WARN_ONCE(1, "Unknown prange 0x%p work op %d\n", prange,
|
||||||
prange->work_item.op);
|
prange->work_item.op);
|
||||||
|
@ -2301,7 +2348,7 @@ svm_range_set_attr(struct kfd_process *p, uint64_t start, uint64_t size,
|
||||||
if (r)
|
if (r)
|
||||||
goto out_unlock_range;
|
goto out_unlock_range;
|
||||||
|
|
||||||
if (migrated) {
|
if (migrated && !p->xnack_enabled) {
|
||||||
pr_debug("restore_work will update mappings of GPUs\n");
|
pr_debug("restore_work will update mappings of GPUs\n");
|
||||||
mutex_unlock(&prange->migrate_mutex);
|
mutex_unlock(&prange->migrate_mutex);
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -44,7 +44,9 @@ enum svm_work_list_ops {
|
||||||
SVM_OP_NULL,
|
SVM_OP_NULL,
|
||||||
SVM_OP_UNMAP_RANGE,
|
SVM_OP_UNMAP_RANGE,
|
||||||
SVM_OP_UPDATE_RANGE_NOTIFIER,
|
SVM_OP_UPDATE_RANGE_NOTIFIER,
|
||||||
SVM_OP_ADD_RANGE
|
SVM_OP_UPDATE_RANGE_NOTIFIER_AND_MAP,
|
||||||
|
SVM_OP_ADD_RANGE,
|
||||||
|
SVM_OP_ADD_RANGE_AND_MAP
|
||||||
};
|
};
|
||||||
|
|
||||||
struct svm_work_list_item {
|
struct svm_work_list_item {
|
||||||
|
|
Loading…
Add table
Reference in a new issue