Skip to content

Commit 2f617f4

Browse files
PhilipYangAalexdeucher
authored andcommitted
drm/amdkfd: map SVM range with correct access permission
Restore retry fault or prefetch range, or restore svm range after eviction to map range to GPU with correct read or write access permission. Range may includes multiple VMAs, update GPU page table with offset of prange, number of pages for each VMA according VMA access permission. Signed-off-by: Philip Yang <[email protected]> Reviewed-by: Felix Kuehling <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
1 parent ff891a2 commit 2f617f4

File tree

1 file changed

+86
-48
lines changed

1 file changed

+86
-48
lines changed

drivers/gpu/drm/amd/amdkfd/kfd_svm.c

Lines changed: 86 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ static void svm_range_remove_notifier(struct svm_range *prange)
120120

121121
static int
122122
svm_range_dma_map_dev(struct amdgpu_device *adev, struct svm_range *prange,
123+
unsigned long offset, unsigned long npages,
123124
unsigned long *hmm_pfns, uint32_t gpuidx)
124125
{
125126
enum dma_data_direction dir = DMA_BIDIRECTIONAL;
@@ -136,7 +137,8 @@ svm_range_dma_map_dev(struct amdgpu_device *adev, struct svm_range *prange,
136137
prange->dma_addr[gpuidx] = addr;
137138
}
138139

139-
for (i = 0; i < prange->npages; i++) {
140+
addr += offset;
141+
for (i = 0; i < npages; i++) {
140142
if (WARN_ONCE(addr[i] && !dma_mapping_error(dev, addr[i]),
141143
"leaking dma mapping\n"))
142144
dma_unmap_page(dev, addr[i], PAGE_SIZE, dir);
@@ -167,6 +169,7 @@ svm_range_dma_map_dev(struct amdgpu_device *adev, struct svm_range *prange,
167169

168170
static int
169171
svm_range_dma_map(struct svm_range *prange, unsigned long *bitmap,
172+
unsigned long offset, unsigned long npages,
170173
unsigned long *hmm_pfns)
171174
{
172175
struct kfd_process *p;
@@ -187,7 +190,8 @@ svm_range_dma_map(struct svm_range *prange, unsigned long *bitmap,
187190
}
188191
adev = (struct amdgpu_device *)pdd->dev->kgd;
189192

190-
r = svm_range_dma_map_dev(adev, prange, hmm_pfns, gpuidx);
193+
r = svm_range_dma_map_dev(adev, prange, offset, npages,
194+
hmm_pfns, gpuidx);
191195
if (r)
192196
break;
193197
}
@@ -1088,11 +1092,6 @@ svm_range_get_pte_flags(struct amdgpu_device *adev, struct svm_range *prange,
10881092
pte_flags |= snoop ? AMDGPU_PTE_SNOOPED : 0;
10891093

10901094
pte_flags |= amdgpu_gem_va_map_flags(adev, mapping_flags);
1091-
1092-
pr_debug("svms 0x%p [0x%lx 0x%lx] vram %d PTE 0x%llx mapping 0x%x\n",
1093-
prange->svms, prange->start, prange->last,
1094-
(domain == SVM_RANGE_VRAM_DOMAIN) ? 1:0, pte_flags, mapping_flags);
1095-
10961095
return pte_flags;
10971096
}
10981097

@@ -1156,7 +1155,8 @@ svm_range_unmap_from_gpus(struct svm_range *prange, unsigned long start,
11561155

11571156
static int
11581157
svm_range_map_to_gpu(struct amdgpu_device *adev, struct amdgpu_vm *vm,
1159-
struct svm_range *prange, dma_addr_t *dma_addr,
1158+
struct svm_range *prange, unsigned long offset,
1159+
unsigned long npages, bool readonly, dma_addr_t *dma_addr,
11601160
struct amdgpu_device *bo_adev, struct dma_fence **fence)
11611161
{
11621162
struct amdgpu_bo_va bo_va;
@@ -1167,14 +1167,15 @@ svm_range_map_to_gpu(struct amdgpu_device *adev, struct amdgpu_vm *vm,
11671167
int r = 0;
11681168
int64_t i;
11691169

1170-
pr_debug("svms 0x%p [0x%lx 0x%lx]\n", prange->svms, prange->start,
1171-
prange->last);
1170+
last_start = prange->start + offset;
1171+
1172+
pr_debug("svms 0x%p [0x%lx 0x%lx] readonly %d\n", prange->svms,
1173+
last_start, last_start + npages - 1, readonly);
11721174

11731175
if (prange->svm_bo && prange->ttm_res)
11741176
bo_va.is_xgmi = amdgpu_xgmi_same_hive(adev, bo_adev);
11751177

1176-
last_start = prange->start;
1177-
for (i = 0; i < prange->npages; i++) {
1178+
for (i = offset; i < offset + npages; i++) {
11781179
last_domain = dma_addr[i] & SVM_RANGE_VRAM_DOMAIN;
11791180
dma_addr[i] &= ~SVM_RANGE_VRAM_DOMAIN;
11801181
if ((prange->start + i) < prange->last &&
@@ -1183,13 +1184,21 @@ svm_range_map_to_gpu(struct amdgpu_device *adev, struct amdgpu_vm *vm,
11831184

11841185
pr_debug("Mapping range [0x%lx 0x%llx] on domain: %s\n",
11851186
last_start, prange->start + i, last_domain ? "GPU" : "CPU");
1187+
11861188
pte_flags = svm_range_get_pte_flags(adev, prange, last_domain);
1187-
r = amdgpu_vm_bo_update_mapping(adev, bo_adev, vm, false, false, NULL,
1188-
last_start,
1189+
if (readonly)
1190+
pte_flags &= ~AMDGPU_PTE_WRITEABLE;
1191+
1192+
pr_debug("svms 0x%p map [0x%lx 0x%llx] vram %d PTE 0x%llx\n",
1193+
prange->svms, last_start, prange->start + i,
1194+
(last_domain == SVM_RANGE_VRAM_DOMAIN) ? 1 : 0,
1195+
pte_flags);
1196+
1197+
r = amdgpu_vm_bo_update_mapping(adev, bo_adev, vm, false, false,
1198+
NULL, last_start,
11891199
prange->start + i, pte_flags,
11901200
last_start - prange->start,
1191-
NULL,
1192-
dma_addr,
1201+
NULL, dma_addr,
11931202
&vm->last_update,
11941203
&table_freed);
11951204
if (r) {
@@ -1220,8 +1229,10 @@ svm_range_map_to_gpu(struct amdgpu_device *adev, struct amdgpu_vm *vm,
12201229
return r;
12211230
}
12221231

1223-
static int svm_range_map_to_gpus(struct svm_range *prange,
1224-
unsigned long *bitmap, bool wait)
1232+
static int
1233+
svm_range_map_to_gpus(struct svm_range *prange, unsigned long offset,
1234+
unsigned long npages, bool readonly,
1235+
unsigned long *bitmap, bool wait)
12251236
{
12261237
struct kfd_process_device *pdd;
12271238
struct amdgpu_device *bo_adev;
@@ -1257,7 +1268,8 @@ static int svm_range_map_to_gpus(struct svm_range *prange,
12571268
}
12581269

12591270
r = svm_range_map_to_gpu(adev, drm_priv_to_vm(pdd->drm_priv),
1260-
prange, prange->dma_addr[gpuidx],
1271+
prange, offset, npages, readonly,
1272+
prange->dma_addr[gpuidx],
12611273
bo_adev, wait ? &fence : NULL);
12621274
if (r)
12631275
break;
@@ -1390,7 +1402,7 @@ static int svm_range_validate_and_map(struct mm_struct *mm,
13901402
int32_t gpuidx, bool intr, bool wait)
13911403
{
13921404
struct svm_validate_context ctx;
1393-
struct hmm_range *hmm_range;
1405+
unsigned long start, end, addr;
13941406
struct kfd_process *p;
13951407
void *owner;
13961408
int32_t idx;
@@ -1448,40 +1460,66 @@ static int svm_range_validate_and_map(struct mm_struct *mm,
14481460
break;
14491461
}
14501462
}
1451-
r = amdgpu_hmm_range_get_pages(&prange->notifier, mm, NULL,
1452-
prange->start << PAGE_SHIFT,
1453-
prange->npages, &hmm_range,
1454-
false, true, owner);
1455-
if (r) {
1456-
pr_debug("failed %d to get svm range pages\n", r);
1457-
goto unreserve_out;
1458-
}
14591463

1460-
r = svm_range_dma_map(prange, ctx.bitmap,
1461-
hmm_range->hmm_pfns);
1462-
if (r) {
1463-
pr_debug("failed %d to dma map range\n", r);
1464-
goto unreserve_out;
1465-
}
1464+
start = prange->start << PAGE_SHIFT;
1465+
end = (prange->last + 1) << PAGE_SHIFT;
1466+
for (addr = start; addr < end && !r; ) {
1467+
struct hmm_range *hmm_range;
1468+
struct vm_area_struct *vma;
1469+
unsigned long next;
1470+
unsigned long offset;
1471+
unsigned long npages;
1472+
bool readonly;
14661473

1467-
prange->validated_once = true;
1474+
vma = find_vma(mm, addr);
1475+
if (!vma || addr < vma->vm_start) {
1476+
r = -EFAULT;
1477+
goto unreserve_out;
1478+
}
1479+
readonly = !(vma->vm_flags & VM_WRITE);
14681480

1469-
svm_range_lock(prange);
1470-
if (amdgpu_hmm_range_get_pages_done(hmm_range)) {
1471-
pr_debug("hmm update the range, need validate again\n");
1472-
r = -EAGAIN;
1473-
goto unlock_out;
1474-
}
1475-
if (!list_empty(&prange->child_list)) {
1476-
pr_debug("range split by unmap in parallel, validate again\n");
1477-
r = -EAGAIN;
1478-
goto unlock_out;
1479-
}
1481+
next = min(vma->vm_end, end);
1482+
npages = (next - addr) >> PAGE_SHIFT;
1483+
r = amdgpu_hmm_range_get_pages(&prange->notifier, mm, NULL,
1484+
addr, npages, &hmm_range,
1485+
readonly, true, owner);
1486+
if (r) {
1487+
pr_debug("failed %d to get svm range pages\n", r);
1488+
goto unreserve_out;
1489+
}
14801490

1481-
r = svm_range_map_to_gpus(prange, ctx.bitmap, wait);
1491+
offset = (addr - start) >> PAGE_SHIFT;
1492+
r = svm_range_dma_map(prange, ctx.bitmap, offset, npages,
1493+
hmm_range->hmm_pfns);
1494+
if (r) {
1495+
pr_debug("failed %d to dma map range\n", r);
1496+
goto unreserve_out;
1497+
}
1498+
1499+
svm_range_lock(prange);
1500+
if (amdgpu_hmm_range_get_pages_done(hmm_range)) {
1501+
pr_debug("hmm update the range, need validate again\n");
1502+
r = -EAGAIN;
1503+
goto unlock_out;
1504+
}
1505+
if (!list_empty(&prange->child_list)) {
1506+
pr_debug("range split by unmap in parallel, validate again\n");
1507+
r = -EAGAIN;
1508+
goto unlock_out;
1509+
}
1510+
1511+
r = svm_range_map_to_gpus(prange, offset, npages, readonly,
1512+
ctx.bitmap, wait);
14821513

14831514
unlock_out:
1484-
svm_range_unlock(prange);
1515+
svm_range_unlock(prange);
1516+
1517+
addr = next;
1518+
}
1519+
1520+
if (addr == end)
1521+
prange->validated_once = true;
1522+
14851523
unreserve_out:
14861524
svm_range_unreserve_bos(&ctx);
14871525

0 commit comments

Comments
 (0)