Commit 74c5b85d authored by Mukul Joshi's avatar Mukul Joshi Committed by Alex Deucher

drm/amdkfd: Add spatial partitioning support in KFD

This patch introduces multi-partition support in KFD.
This patch includes:
- Support for maximum 8 spatial partitions in KFD.
- Initialize one HIQ per partition.
- Management of VMID range depending on partition mode.
- Management of doorbell aperture space between all
  partitions.
- Each partition does its own queue management, interrupt
  handling, SMI event reporting.
- IOMMU, if enabled with multiple partitions, will only work
  on first partition.
- SPM is only supported on the first partition.
- Currently, there is no support for resetting individual
  partitions. All partitions will reset together.
Signed-off-by: default avatarMukul Joshi <mukul.joshi@amd.com>
Tested-by: default avatarAmber Lin <Amber.Lin@amd.com>
Reviewed-by: default avatarFelix Kuehling <Felix.Kuehling@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 8dc1db31
This diff is collapsed.
...@@ -1426,7 +1426,7 @@ static int set_sched_resources(struct device_queue_manager *dqm) ...@@ -1426,7 +1426,7 @@ static int set_sched_resources(struct device_queue_manager *dqm)
int i, mec; int i, mec;
struct scheduling_resources res; struct scheduling_resources res;
res.vmid_mask = dqm->dev->kfd->shared_resources.compute_vmid_bitmap; res.vmid_mask = dqm->dev->compute_vmid_bitmap;
res.queue_mask = 0; res.queue_mask = 0;
for (i = 0; i < KGD_MAX_QUEUES; ++i) { for (i = 0; i < KGD_MAX_QUEUES; ++i) {
......
...@@ -121,6 +121,12 @@ int kfd_iommu_bind_process_to_device(struct kfd_process_device *pdd) ...@@ -121,6 +121,12 @@ int kfd_iommu_bind_process_to_device(struct kfd_process_device *pdd)
return -EINVAL; return -EINVAL;
} }
if (!kfd_is_first_node(dev)) {
dev_warn_once(kfd_device,
"IOMMU supported only on first node\n");
return 0;
}
err = amd_iommu_bind_pasid(dev->adev->pdev, p->pasid, p->lead_thread); err = amd_iommu_bind_pasid(dev->adev->pdev, p->pasid, p->lead_thread);
if (!err) if (!err)
pdd->bound = PDD_BOUND; pdd->bound = PDD_BOUND;
...@@ -138,7 +144,8 @@ void kfd_iommu_unbind_process(struct kfd_process *p) ...@@ -138,7 +144,8 @@ void kfd_iommu_unbind_process(struct kfd_process *p)
int i; int i;
for (i = 0; i < p->n_pdds; i++) for (i = 0; i < p->n_pdds; i++)
if (p->pdds[i]->bound == PDD_BOUND) if ((p->pdds[i]->bound == PDD_BOUND) &&
(kfd_is_first_node((p->pdds[i]->dev))))
amd_iommu_unbind_pasid(p->pdds[i]->dev->adev->pdev, amd_iommu_unbind_pasid(p->pdds[i]->dev->adev->pdev,
p->pasid); p->pasid);
} }
...@@ -281,7 +288,7 @@ void kfd_iommu_suspend(struct kfd_dev *kfd) ...@@ -281,7 +288,7 @@ void kfd_iommu_suspend(struct kfd_dev *kfd)
if (!kfd->use_iommu_v2) if (!kfd->use_iommu_v2)
return; return;
kfd_unbind_processes_from_device(kfd->node); kfd_unbind_processes_from_device(kfd->nodes[0]);
amd_iommu_set_invalidate_ctx_cb(kfd->adev->pdev, NULL); amd_iommu_set_invalidate_ctx_cb(kfd->adev->pdev, NULL);
amd_iommu_set_invalid_ppr_cb(kfd->adev->pdev, NULL); amd_iommu_set_invalid_ppr_cb(kfd->adev->pdev, NULL);
...@@ -312,7 +319,7 @@ int kfd_iommu_resume(struct kfd_dev *kfd) ...@@ -312,7 +319,7 @@ int kfd_iommu_resume(struct kfd_dev *kfd)
amd_iommu_set_invalid_ppr_cb(kfd->adev->pdev, amd_iommu_set_invalid_ppr_cb(kfd->adev->pdev,
iommu_invalid_ppr_cb); iommu_invalid_ppr_cb);
err = kfd_bind_processes_to_device(kfd->node); err = kfd_bind_processes_to_device(kfd->nodes[0]);
if (err) { if (err) {
amd_iommu_set_invalidate_ctx_cb(kfd->adev->pdev, NULL); amd_iommu_set_invalidate_ctx_cb(kfd->adev->pdev, NULL);
amd_iommu_set_invalid_ppr_cb(kfd->adev->pdev, NULL); amd_iommu_set_invalid_ppr_cb(kfd->adev->pdev, NULL);
......
...@@ -423,7 +423,7 @@ svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct svm_range *prange, ...@@ -423,7 +423,7 @@ svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
kfd_smi_event_migration_start(adev->kfd.dev, p->lead_thread->pid, kfd_smi_event_migration_start(adev->kfd.dev, p->lead_thread->pid,
start >> PAGE_SHIFT, end >> PAGE_SHIFT, start >> PAGE_SHIFT, end >> PAGE_SHIFT,
0, adev->kfd.dev->node->id, prange->prefetch_loc, 0, adev->kfd.dev->nodes[0]->id, prange->prefetch_loc,
prange->preferred_loc, trigger); prange->preferred_loc, trigger);
r = migrate_vma_setup(&migrate); r = migrate_vma_setup(&migrate);
...@@ -456,7 +456,7 @@ svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct svm_range *prange, ...@@ -456,7 +456,7 @@ svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
kfd_smi_event_migration_end(adev->kfd.dev, p->lead_thread->pid, kfd_smi_event_migration_end(adev->kfd.dev, p->lead_thread->pid,
start >> PAGE_SHIFT, end >> PAGE_SHIFT, start >> PAGE_SHIFT, end >> PAGE_SHIFT,
0, adev->kfd.dev->node->id, trigger); 0, adev->kfd.dev->nodes[0]->id, trigger);
svm_range_dma_unmap(adev->dev, scratch, 0, npages); svm_range_dma_unmap(adev->dev, scratch, 0, npages);
svm_range_free_dma_mappings(prange); svm_range_free_dma_mappings(prange);
...@@ -701,7 +701,7 @@ svm_migrate_vma_to_ram(struct amdgpu_device *adev, struct svm_range *prange, ...@@ -701,7 +701,7 @@ svm_migrate_vma_to_ram(struct amdgpu_device *adev, struct svm_range *prange,
kfd_smi_event_migration_start(adev->kfd.dev, p->lead_thread->pid, kfd_smi_event_migration_start(adev->kfd.dev, p->lead_thread->pid,
start >> PAGE_SHIFT, end >> PAGE_SHIFT, start >> PAGE_SHIFT, end >> PAGE_SHIFT,
adev->kfd.dev->node->id, 0, prange->prefetch_loc, adev->kfd.dev->nodes[0]->id, 0, prange->prefetch_loc,
prange->preferred_loc, trigger); prange->preferred_loc, trigger);
r = migrate_vma_setup(&migrate); r = migrate_vma_setup(&migrate);
...@@ -737,7 +737,7 @@ svm_migrate_vma_to_ram(struct amdgpu_device *adev, struct svm_range *prange, ...@@ -737,7 +737,7 @@ svm_migrate_vma_to_ram(struct amdgpu_device *adev, struct svm_range *prange,
kfd_smi_event_migration_end(adev->kfd.dev, p->lead_thread->pid, kfd_smi_event_migration_end(adev->kfd.dev, p->lead_thread->pid,
start >> PAGE_SHIFT, end >> PAGE_SHIFT, start >> PAGE_SHIFT, end >> PAGE_SHIFT,
adev->kfd.dev->node->id, 0, trigger); adev->kfd.dev->nodes[0]->id, 0, trigger);
svm_range_dma_unmap(adev->dev, scratch, 0, npages); svm_range_dma_unmap(adev->dev, scratch, 0, npages);
......
...@@ -255,6 +255,8 @@ struct kfd_vmid_info { ...@@ -255,6 +255,8 @@ struct kfd_vmid_info {
uint32_t vmid_num_kfd; uint32_t vmid_num_kfd;
}; };
#define MAX_KFD_NODES 8
struct kfd_dev; struct kfd_dev;
struct kfd_node { struct kfd_node {
...@@ -267,6 +269,10 @@ struct kfd_node { ...@@ -267,6 +269,10 @@ struct kfd_node {
*/ */
struct kfd_vmid_info vm_info; struct kfd_vmid_info vm_info;
unsigned int id; /* topology stub index */ unsigned int id; /* topology stub index */
unsigned int num_xcc_per_node;
unsigned int start_xcc_id; /* Starting XCC instance
* number for the node
*/
/* Interrupts */ /* Interrupts */
struct kfifo ih_fifo; struct kfifo ih_fifo;
struct workqueue_struct *ih_wq; struct workqueue_struct *ih_wq;
...@@ -300,6 +306,8 @@ struct kfd_node { ...@@ -300,6 +306,8 @@ struct kfd_node {
/* Maximum process number mapped to HW scheduler */ /* Maximum process number mapped to HW scheduler */
unsigned int max_proc_per_quantum; unsigned int max_proc_per_quantum;
unsigned int compute_vmid_bitmap;
struct kfd_dev *kfd; struct kfd_dev *kfd;
}; };
...@@ -368,7 +376,8 @@ struct kfd_dev { ...@@ -368,7 +376,8 @@ struct kfd_dev {
/* HMM page migration MEMORY_DEVICE_PRIVATE mapping */ /* HMM page migration MEMORY_DEVICE_PRIVATE mapping */
struct dev_pagemap pgmap; struct dev_pagemap pgmap;
struct kfd_node *node; struct kfd_node *nodes[MAX_KFD_NODES];
unsigned int num_nodes;
}; };
enum kfd_mempool { enum kfd_mempool {
...@@ -1397,6 +1406,11 @@ static inline int kfd_devcgroup_check_permission(struct kfd_node *kfd) ...@@ -1397,6 +1406,11 @@ static inline int kfd_devcgroup_check_permission(struct kfd_node *kfd)
#endif #endif
} }
static inline bool kfd_is_first_node(struct kfd_node *node)
{
return (node == node->kfd->nodes[0]);
}
/* Debugfs */ /* Debugfs */
#if defined(CONFIG_DEBUG_FS) #if defined(CONFIG_DEBUG_FS)
......
...@@ -254,17 +254,17 @@ void kfd_smi_event_page_fault_start(struct kfd_dev *dev, pid_t pid, ...@@ -254,17 +254,17 @@ void kfd_smi_event_page_fault_start(struct kfd_dev *dev, pid_t pid,
unsigned long address, bool write_fault, unsigned long address, bool write_fault,
ktime_t ts) ktime_t ts)
{ {
kfd_smi_event_add(pid, dev->node, KFD_SMI_EVENT_PAGE_FAULT_START, kfd_smi_event_add(pid, dev->nodes[0], KFD_SMI_EVENT_PAGE_FAULT_START,
"%lld -%d @%lx(%x) %c\n", ktime_to_ns(ts), pid, "%lld -%d @%lx(%x) %c\n", ktime_to_ns(ts), pid,
address, dev->node->id, write_fault ? 'W' : 'R'); address, dev->nodes[0]->id, write_fault ? 'W' : 'R');
} }
void kfd_smi_event_page_fault_end(struct kfd_dev *dev, pid_t pid, void kfd_smi_event_page_fault_end(struct kfd_dev *dev, pid_t pid,
unsigned long address, bool migration) unsigned long address, bool migration)
{ {
kfd_smi_event_add(pid, dev->node, KFD_SMI_EVENT_PAGE_FAULT_END, kfd_smi_event_add(pid, dev->nodes[0], KFD_SMI_EVENT_PAGE_FAULT_END,
"%lld -%d @%lx(%x) %c\n", ktime_get_boottime_ns(), "%lld -%d @%lx(%x) %c\n", ktime_get_boottime_ns(),
pid, address, dev->node->id, migration ? 'M' : 'U'); pid, address, dev->nodes[0]->id, migration ? 'M' : 'U');
} }
void kfd_smi_event_migration_start(struct kfd_dev *dev, pid_t pid, void kfd_smi_event_migration_start(struct kfd_dev *dev, pid_t pid,
...@@ -273,7 +273,7 @@ void kfd_smi_event_migration_start(struct kfd_dev *dev, pid_t pid, ...@@ -273,7 +273,7 @@ void kfd_smi_event_migration_start(struct kfd_dev *dev, pid_t pid,
uint32_t prefetch_loc, uint32_t preferred_loc, uint32_t prefetch_loc, uint32_t preferred_loc,
uint32_t trigger) uint32_t trigger)
{ {
kfd_smi_event_add(pid, dev->node, KFD_SMI_EVENT_MIGRATE_START, kfd_smi_event_add(pid, dev->nodes[0], KFD_SMI_EVENT_MIGRATE_START,
"%lld -%d @%lx(%lx) %x->%x %x:%x %d\n", "%lld -%d @%lx(%lx) %x->%x %x:%x %d\n",
ktime_get_boottime_ns(), pid, start, end - start, ktime_get_boottime_ns(), pid, start, end - start,
from, to, prefetch_loc, preferred_loc, trigger); from, to, prefetch_loc, preferred_loc, trigger);
...@@ -283,7 +283,7 @@ void kfd_smi_event_migration_end(struct kfd_dev *dev, pid_t pid, ...@@ -283,7 +283,7 @@ void kfd_smi_event_migration_end(struct kfd_dev *dev, pid_t pid,
unsigned long start, unsigned long end, unsigned long start, unsigned long end,
uint32_t from, uint32_t to, uint32_t trigger) uint32_t from, uint32_t to, uint32_t trigger)
{ {
kfd_smi_event_add(pid, dev->node, KFD_SMI_EVENT_MIGRATE_END, kfd_smi_event_add(pid, dev->nodes[0], KFD_SMI_EVENT_MIGRATE_END,
"%lld -%d @%lx(%lx) %x->%x %d\n", "%lld -%d @%lx(%lx) %x->%x %d\n",
ktime_get_boottime_ns(), pid, start, end - start, ktime_get_boottime_ns(), pid, start, end - start,
from, to, trigger); from, to, trigger);
...@@ -292,16 +292,16 @@ void kfd_smi_event_migration_end(struct kfd_dev *dev, pid_t pid, ...@@ -292,16 +292,16 @@ void kfd_smi_event_migration_end(struct kfd_dev *dev, pid_t pid,
void kfd_smi_event_queue_eviction(struct kfd_dev *dev, pid_t pid, void kfd_smi_event_queue_eviction(struct kfd_dev *dev, pid_t pid,
uint32_t trigger) uint32_t trigger)
{ {
kfd_smi_event_add(pid, dev->node, KFD_SMI_EVENT_QUEUE_EVICTION, kfd_smi_event_add(pid, dev->nodes[0], KFD_SMI_EVENT_QUEUE_EVICTION,
"%lld -%d %x %d\n", ktime_get_boottime_ns(), pid, "%lld -%d %x %d\n", ktime_get_boottime_ns(), pid,
dev->node->id, trigger); dev->nodes[0]->id, trigger);
} }
void kfd_smi_event_queue_restore(struct kfd_dev *dev, pid_t pid) void kfd_smi_event_queue_restore(struct kfd_dev *dev, pid_t pid)
{ {
kfd_smi_event_add(pid, dev->node, KFD_SMI_EVENT_QUEUE_RESTORE, kfd_smi_event_add(pid, dev->nodes[0], KFD_SMI_EVENT_QUEUE_RESTORE,
"%lld -%d %x\n", ktime_get_boottime_ns(), pid, "%lld -%d %x\n", ktime_get_boottime_ns(), pid,
dev->node->id); dev->nodes[0]->id);
} }
void kfd_smi_event_queue_restore_rescheduled(struct mm_struct *mm) void kfd_smi_event_queue_restore_rescheduled(struct mm_struct *mm)
...@@ -328,9 +328,9 @@ void kfd_smi_event_unmap_from_gpu(struct kfd_dev *dev, pid_t pid, ...@@ -328,9 +328,9 @@ void kfd_smi_event_unmap_from_gpu(struct kfd_dev *dev, pid_t pid,
unsigned long address, unsigned long last, unsigned long address, unsigned long last,
uint32_t trigger) uint32_t trigger)
{ {
kfd_smi_event_add(pid, dev->node, KFD_SMI_EVENT_UNMAP_FROM_GPU, kfd_smi_event_add(pid, dev->nodes[0], KFD_SMI_EVENT_UNMAP_FROM_GPU,
"%lld -%d @%lx(%lx) %x %d\n", ktime_get_boottime_ns(), "%lld -%d @%lx(%lx) %x %d\n", ktime_get_boottime_ns(),
pid, address, last - address + 1, dev->node->id, trigger); pid, address, last - address + 1, dev->nodes[0]->id, trigger);
} }
int kfd_smi_event_open(struct kfd_node *dev, uint32_t *fd) int kfd_smi_event_open(struct kfd_node *dev, uint32_t *fd)
......
...@@ -555,7 +555,8 @@ static ssize_t node_show(struct kobject *kobj, struct attribute *attr, ...@@ -555,7 +555,8 @@ static ssize_t node_show(struct kobject *kobj, struct attribute *attr,
dev->gpu->kfd->sdma_fw_version); dev->gpu->kfd->sdma_fw_version);
sysfs_show_64bit_prop(buffer, offs, "unique_id", sysfs_show_64bit_prop(buffer, offs, "unique_id",
dev->gpu->adev->unique_id); dev->gpu->adev->unique_id);
sysfs_show_32bit_prop(buffer, offs, "num_xcc",
dev->gpu->num_xcc_per_node);
} }
return sysfs_show_32bit_prop(buffer, offs, "max_engine_clk_ccompute", return sysfs_show_32bit_prop(buffer, offs, "max_engine_clk_ccompute",
...@@ -1160,7 +1161,7 @@ void kfd_topology_shutdown(void) ...@@ -1160,7 +1161,7 @@ void kfd_topology_shutdown(void)
static uint32_t kfd_generate_gpu_id(struct kfd_node *gpu) static uint32_t kfd_generate_gpu_id(struct kfd_node *gpu)
{ {
uint32_t hashout; uint32_t hashout;
uint32_t buf[7]; uint32_t buf[8];
uint64_t local_mem_size; uint64_t local_mem_size;
int i; int i;
...@@ -1177,8 +1178,9 @@ static uint32_t kfd_generate_gpu_id(struct kfd_node *gpu) ...@@ -1177,8 +1178,9 @@ static uint32_t kfd_generate_gpu_id(struct kfd_node *gpu)
buf[4] = gpu->adev->pdev->bus->number; buf[4] = gpu->adev->pdev->bus->number;
buf[5] = lower_32_bits(local_mem_size); buf[5] = lower_32_bits(local_mem_size);
buf[6] = upper_32_bits(local_mem_size); buf[6] = upper_32_bits(local_mem_size);
buf[7] = gpu->start_xcc_id | (gpu->num_xcc_per_node << 16);
for (i = 0, hashout = 0; i < 7; i++) for (i = 0, hashout = 0; i < 8; i++)
hashout ^= hash_32(buf[i], KFD_GPU_ID_HASH_WIDTH); hashout ^= hash_32(buf[i], KFD_GPU_ID_HASH_WIDTH);
return hashout; return hashout;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment