diff options
author | Felix Kuehling <Felix.Kuehling@amd.com> | 2018-02-06 20:32:44 -0500 |
---|---|---|
committer | Oded Gabbay <oded.gabbay@gmail.com> | 2018-02-06 20:32:44 -0500 |
commit | 403575c44e61722ae443b47df66e188b367d7324 (patch) | |
tree | a12e3a6e8770068e58363cb9076346fe9a9600b3 | |
parent | 4252bf686622f6c71958c4fabbcb6a64deba1cf7 (diff) |
drm/amdkfd: Add GPUVM virtual address space to PDD
Create/destroy the GPUVM context during PDD creation/destruction.
Get VM page table base and program it during process registration
(HWS) or VMID allocation (non-HWS).
v2:
* Used dev instead of pdd->dev in kfd_flush_tlb
Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com>
Acked-by: Oded Gabbay <oded.gabbay@gmail.com>
Signed-off-by: Oded Gabbay <oded.gabbay@gmail.com>
-rw-r--r-- | drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 20 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdkfd/kfd_process.c | 33 |
3 files changed, 66 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index 1a28dc2c661e..b7d06395d592 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | |||
@@ -129,6 +129,15 @@ static int allocate_vmid(struct device_queue_manager *dqm, | |||
129 | set_pasid_vmid_mapping(dqm, q->process->pasid, q->properties.vmid); | 129 | set_pasid_vmid_mapping(dqm, q->process->pasid, q->properties.vmid); |
130 | program_sh_mem_settings(dqm, qpd); | 130 | program_sh_mem_settings(dqm, qpd); |
131 | 131 | ||
132 | /* qpd->page_table_base is set earlier when register_process() | ||
133 | * is called, i.e. when the first queue is created. | ||
134 | */ | ||
135 | dqm->dev->kfd2kgd->set_vm_context_page_table_base(dqm->dev->kgd, | ||
136 | qpd->vmid, | ||
137 | qpd->page_table_base); | ||
138 | /* invalidate the VM context after pasid and vmid mapping is set up */ | ||
139 | kfd_flush_tlb(qpd_to_pdd(qpd)); | ||
140 | |||
132 | return 0; | 141 | return 0; |
133 | } | 142 | } |
134 | 143 | ||
@@ -138,6 +147,8 @@ static void deallocate_vmid(struct device_queue_manager *dqm, | |||
138 | { | 147 | { |
139 | int bit = qpd->vmid - dqm->dev->vm_info.first_vmid_kfd; | 148 | int bit = qpd->vmid - dqm->dev->vm_info.first_vmid_kfd; |
140 | 149 | ||
150 | kfd_flush_tlb(qpd_to_pdd(qpd)); | ||
151 | |||
141 | /* Release the vmid mapping */ | 152 | /* Release the vmid mapping */ |
142 | set_pasid_vmid_mapping(dqm, 0, qpd->vmid); | 153 | set_pasid_vmid_mapping(dqm, 0, qpd->vmid); |
143 | 154 | ||
@@ -450,6 +461,8 @@ static int register_process(struct device_queue_manager *dqm, | |||
450 | struct qcm_process_device *qpd) | 461 | struct qcm_process_device *qpd) |
451 | { | 462 | { |
452 | struct device_process_node *n; | 463 | struct device_process_node *n; |
464 | struct kfd_process_device *pdd; | ||
465 | uint32_t pd_base; | ||
453 | int retval; | 466 | int retval; |
454 | 467 | ||
455 | n = kzalloc(sizeof(*n), GFP_KERNEL); | 468 | n = kzalloc(sizeof(*n), GFP_KERNEL); |
@@ -458,9 +471,16 @@ static int register_process(struct device_queue_manager *dqm, | |||
458 | 471 | ||
459 | n->qpd = qpd; | 472 | n->qpd = qpd; |
460 | 473 | ||
474 | pdd = qpd_to_pdd(qpd); | ||
475 | /* Retrieve PD base */ | ||
476 | pd_base = dqm->dev->kfd2kgd->get_process_page_dir(pdd->vm); | ||
477 | |||
461 | mutex_lock(&dqm->lock); | 478 | mutex_lock(&dqm->lock); |
462 | list_add(&n->list, &dqm->queues); | 479 | list_add(&n->list, &dqm->queues); |
463 | 480 | ||
481 | /* Update PD Base in QPD */ | ||
482 | qpd->page_table_base = pd_base; | ||
483 | |||
464 | retval = dqm->asic_ops.update_qpd(dqm, qpd); | 484 | retval = dqm->asic_ops.update_qpd(dqm, qpd); |
465 | 485 | ||
466 | dqm->processes_count++; | 486 | dqm->processes_count++; |
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index f12eb5d98be8..56c2e368f702 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h | |||
@@ -518,6 +518,9 @@ struct kfd_process_device { | |||
518 | uint64_t scratch_base; | 518 | uint64_t scratch_base; |
519 | uint64_t scratch_limit; | 519 | uint64_t scratch_limit; |
520 | 520 | ||
521 | /* VM context for GPUVM allocations */ | ||
522 | void *vm; | ||
523 | |||
521 | /* Flag used to tell the pdd has dequeued from the dqm. | 524 | /* Flag used to tell the pdd has dequeued from the dqm. |
522 | * This is used to prevent dev->dqm->ops.process_termination() from | 525 | * This is used to prevent dev->dqm->ops.process_termination() from |
523 | * being called twice when it is already called in IOMMU callback | 526 | * being called twice when it is already called in IOMMU callback |
@@ -589,6 +592,14 @@ struct kfd_process { | |||
589 | size_t signal_mapped_size; | 592 | size_t signal_mapped_size; |
590 | size_t signal_event_count; | 593 | size_t signal_event_count; |
591 | bool signal_event_limit_reached; | 594 | bool signal_event_limit_reached; |
595 | |||
596 | /* Information used for memory eviction */ | ||
597 | void *kgd_process_info; | ||
598 | /* Eviction fence that is attached to all the BOs of this process. The | ||
599 | * fence will be triggered during eviction and new one will be created | ||
600 | * during restore | ||
601 | */ | ||
602 | struct dma_fence *ef; | ||
592 | }; | 603 | }; |
593 | 604 | ||
594 | #define KFD_PROCESS_TABLE_SIZE 5 /* bits: 32 entries */ | 605 | #define KFD_PROCESS_TABLE_SIZE 5 /* bits: 32 entries */ |
@@ -802,6 +813,8 @@ int kfd_event_create(struct file *devkfd, struct kfd_process *p, | |||
802 | uint64_t *event_page_offset, uint32_t *event_slot_index); | 813 | uint64_t *event_page_offset, uint32_t *event_slot_index); |
803 | int kfd_event_destroy(struct kfd_process *p, uint32_t event_id); | 814 | int kfd_event_destroy(struct kfd_process *p, uint32_t event_id); |
804 | 815 | ||
816 | void kfd_flush_tlb(struct kfd_process_device *pdd); | ||
817 | |||
805 | int dbgdev_wave_reset_wavefronts(struct kfd_dev *dev, struct kfd_process *p); | 818 | int dbgdev_wave_reset_wavefronts(struct kfd_dev *dev, struct kfd_process *p); |
806 | 819 | ||
807 | /* Debugfs */ | 820 | /* Debugfs */ |
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index e9aee76ceba9..cf4fa25cc430 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c | |||
@@ -34,6 +34,7 @@ | |||
34 | struct mm_struct; | 34 | struct mm_struct; |
35 | 35 | ||
36 | #include "kfd_priv.h" | 36 | #include "kfd_priv.h" |
37 | #include "kfd_device_queue_manager.h" | ||
37 | #include "kfd_dbgmgr.h" | 38 | #include "kfd_dbgmgr.h" |
38 | #include "kfd_iommu.h" | 39 | #include "kfd_iommu.h" |
39 | 40 | ||
@@ -154,6 +155,10 @@ static void kfd_process_destroy_pdds(struct kfd_process *p) | |||
154 | pr_debug("Releasing pdd (topology id %d) for process (pasid %d)\n", | 155 | pr_debug("Releasing pdd (topology id %d) for process (pasid %d)\n", |
155 | pdd->dev->id, p->pasid); | 156 | pdd->dev->id, p->pasid); |
156 | 157 | ||
158 | if (pdd->vm) | ||
159 | pdd->dev->kfd2kgd->destroy_process_vm( | ||
160 | pdd->dev->kgd, pdd->vm); | ||
161 | |||
157 | list_del(&pdd->per_device_list); | 162 | list_del(&pdd->per_device_list); |
158 | 163 | ||
159 | if (pdd->qpd.cwsr_kaddr) | 164 | if (pdd->qpd.cwsr_kaddr) |
@@ -177,6 +182,7 @@ static void kfd_process_wq_release(struct work_struct *work) | |||
177 | kfd_iommu_unbind_process(p); | 182 | kfd_iommu_unbind_process(p); |
178 | 183 | ||
179 | kfd_process_destroy_pdds(p); | 184 | kfd_process_destroy_pdds(p); |
185 | dma_fence_put(p->ef); | ||
180 | 186 | ||
181 | kfd_event_free_process(p); | 187 | kfd_event_free_process(p); |
182 | 188 | ||
@@ -401,7 +407,18 @@ struct kfd_process_device *kfd_create_process_device_data(struct kfd_dev *dev, | |||
401 | pdd->already_dequeued = false; | 407 | pdd->already_dequeued = false; |
402 | list_add(&pdd->per_device_list, &p->per_device_data); | 408 | list_add(&pdd->per_device_list, &p->per_device_data); |
403 | 409 | ||
410 | /* Create the GPUVM context for this specific device */ | ||
411 | if (dev->kfd2kgd->create_process_vm(dev->kgd, &pdd->vm, | ||
412 | &p->kgd_process_info, &p->ef)) { | ||
413 | pr_err("Failed to create process VM object\n"); | ||
414 | goto err_create_pdd; | ||
415 | } | ||
404 | return pdd; | 416 | return pdd; |
417 | |||
418 | err_create_pdd: | ||
419 | list_del(&pdd->per_device_list); | ||
420 | kfree(pdd); | ||
421 | return NULL; | ||
405 | } | 422 | } |
406 | 423 | ||
407 | /* | 424 | /* |
@@ -507,6 +524,22 @@ int kfd_reserved_mem_mmap(struct kfd_process *process, | |||
507 | KFD_CWSR_TBA_TMA_SIZE, vma->vm_page_prot); | 524 | KFD_CWSR_TBA_TMA_SIZE, vma->vm_page_prot); |
508 | } | 525 | } |
509 | 526 | ||
527 | void kfd_flush_tlb(struct kfd_process_device *pdd) | ||
528 | { | ||
529 | struct kfd_dev *dev = pdd->dev; | ||
530 | const struct kfd2kgd_calls *f2g = dev->kfd2kgd; | ||
531 | |||
532 | if (dev->dqm->sched_policy == KFD_SCHED_POLICY_NO_HWS) { | ||
533 | /* Nothing to flush until a VMID is assigned, which | ||
534 | * only happens when the first queue is created. | ||
535 | */ | ||
536 | if (pdd->qpd.vmid) | ||
537 | f2g->invalidate_tlbs_vmid(dev->kgd, pdd->qpd.vmid); | ||
538 | } else { | ||
539 | f2g->invalidate_tlbs(dev->kgd, pdd->process->pasid); | ||
540 | } | ||
541 | } | ||
542 | |||
510 | #if defined(CONFIG_DEBUG_FS) | 543 | #if defined(CONFIG_DEBUG_FS) |
511 | 544 | ||
512 | int kfd_debugfs_mqds_by_process(struct seq_file *m, void *data) | 545 | int kfd_debugfs_mqds_by_process(struct seq_file *m, void *data) |