Commit 42de677f authored by Philip Yang's avatar Philip Yang Committed by Alex Deucher

drm/amdkfd: register svm range

svm range structure stores the range start address, size, attributes,
flags, prefetch location and gpu bitmap which indicates which GPU this
range maps to. Same virtual address is shared by CPU and GPUs.

Process has svm range list which uses both interval tree and list to
store all svm ranges registered by the process. Interval tree is used by
GPU vm fault handler and CPU page fault handler to get svm range
structure from the specific address. List is used to scan all ranges in
eviction restore work.

No overlap range interval [start, last] exist in svms object interval
tree. If process registers new range which has overlap with old range,
the old range split into 2 ranges depending on the overlap happens at
head or tail part of old range.

Apply attributes preferred location, prefetch location, mapping flags,
migration granularity to svm range, store mapping gpu index into bitmap.
Signed-off-by: default avatarPhilip Yang <Philip.Yang@amd.com>
Signed-off-by: default avatarAlex Sierra <alex.sierra@amd.com>
Reviewed-by: default avatarFelix Kuehling <Felix.Kuehling@amd.com>
Signed-off-by: default avatarFelix Kuehling <Felix.Kuehling@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 40ce74d1
...@@ -54,7 +54,8 @@ AMDKFD_FILES := $(AMDKFD_PATH)/kfd_module.o \ ...@@ -54,7 +54,8 @@ AMDKFD_FILES := $(AMDKFD_PATH)/kfd_module.o \
$(AMDKFD_PATH)/kfd_dbgdev.o \ $(AMDKFD_PATH)/kfd_dbgdev.o \
$(AMDKFD_PATH)/kfd_dbgmgr.o \ $(AMDKFD_PATH)/kfd_dbgmgr.o \
$(AMDKFD_PATH)/kfd_smi_events.o \ $(AMDKFD_PATH)/kfd_smi_events.o \
$(AMDKFD_PATH)/kfd_crat.o $(AMDKFD_PATH)/kfd_crat.o \
$(AMDKFD_PATH)/kfd_svm.o
ifneq ($(CONFIG_AMD_IOMMU_V2),) ifneq ($(CONFIG_AMD_IOMMU_V2),)
AMDKFD_FILES += $(AMDKFD_PATH)/kfd_iommu.o AMDKFD_FILES += $(AMDKFD_PATH)/kfd_iommu.o
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include "kfd_priv.h" #include "kfd_priv.h"
#include "kfd_device_queue_manager.h" #include "kfd_device_queue_manager.h"
#include "kfd_dbgmgr.h" #include "kfd_dbgmgr.h"
#include "kfd_svm.h"
#include "amdgpu_amdkfd.h" #include "amdgpu_amdkfd.h"
#include "kfd_smi_events.h" #include "kfd_smi_events.h"
...@@ -1746,11 +1747,27 @@ static int kfd_ioctl_smi_events(struct file *filep, ...@@ -1746,11 +1747,27 @@ static int kfd_ioctl_smi_events(struct file *filep,
static int kfd_ioctl_svm(struct file *filep, struct kfd_process *p, void *data) static int kfd_ioctl_svm(struct file *filep, struct kfd_process *p, void *data)
{ {
struct kfd_ioctl_svm_args *args = data;
int r = 0; int r = 0;
if (p->svm_disabled) if (p->svm_disabled)
return -EPERM; return -EPERM;
pr_debug("start 0x%llx size 0x%llx op 0x%x nattr 0x%x\n",
args->start_addr, args->size, args->op, args->nattr);
if ((args->start_addr & ~PAGE_MASK) || (args->size & ~PAGE_MASK))
return -EINVAL;
if (!args->start_addr || !args->size)
return -EINVAL;
mutex_lock(&p->mutex);
r = svm_ioctl(p, args->op, args->start_addr, args->size, args->nattr,
args->attrs);
mutex_unlock(&p->mutex);
return r; return r;
} }
......
...@@ -731,6 +731,12 @@ struct kfd_process_device { ...@@ -731,6 +731,12 @@ struct kfd_process_device {
#define qpd_to_pdd(x) container_of(x, struct kfd_process_device, qpd) #define qpd_to_pdd(x) container_of(x, struct kfd_process_device, qpd)
struct svm_range_list {
struct mutex lock;
struct rb_root_cached objects;
struct list_head list;
};
/* Process data */ /* Process data */
struct kfd_process { struct kfd_process {
/* /*
...@@ -810,6 +816,8 @@ struct kfd_process { ...@@ -810,6 +816,8 @@ struct kfd_process {
struct kobject *kobj_queues; struct kobject *kobj_queues;
struct attribute attr_pasid; struct attribute attr_pasid;
/* shared virtual memory registered by this process */
struct svm_range_list svms;
bool svm_disabled; bool svm_disabled;
}; };
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include "amdgpu_amdkfd.h" #include "amdgpu_amdkfd.h"
#include "amdgpu.h" #include "amdgpu.h"
#include "kfd_svm.h"
struct mm_struct; struct mm_struct;
...@@ -42,6 +43,7 @@ struct mm_struct; ...@@ -42,6 +43,7 @@ struct mm_struct;
#include "kfd_device_queue_manager.h" #include "kfd_device_queue_manager.h"
#include "kfd_dbgmgr.h" #include "kfd_dbgmgr.h"
#include "kfd_iommu.h" #include "kfd_iommu.h"
#include "kfd_svm.h"
/* /*
* List of struct kfd_process (field kfd_process). * List of struct kfd_process (field kfd_process).
...@@ -1003,6 +1005,7 @@ static void kfd_process_wq_release(struct work_struct *work) ...@@ -1003,6 +1005,7 @@ static void kfd_process_wq_release(struct work_struct *work)
kfd_iommu_unbind_process(p); kfd_iommu_unbind_process(p);
kfd_process_free_outstanding_kfd_bos(p); kfd_process_free_outstanding_kfd_bos(p);
svm_range_list_fini(p);
kfd_process_destroy_pdds(p); kfd_process_destroy_pdds(p);
dma_fence_put(p->ef); dma_fence_put(p->ef);
...@@ -1228,6 +1231,10 @@ static struct kfd_process *create_process(const struct task_struct *thread) ...@@ -1228,6 +1231,10 @@ static struct kfd_process *create_process(const struct task_struct *thread)
if (err != 0) if (err != 0)
goto err_init_apertures; goto err_init_apertures;
err = svm_range_list_init(process);
if (err)
goto err_init_svm_range_list;
/* alloc_notifier needs to find the process in the hash table */ /* alloc_notifier needs to find the process in the hash table */
hash_add_rcu(kfd_processes_table, &process->kfd_processes, hash_add_rcu(kfd_processes_table, &process->kfd_processes,
(uintptr_t)process->mm); (uintptr_t)process->mm);
...@@ -1250,6 +1257,8 @@ static struct kfd_process *create_process(const struct task_struct *thread) ...@@ -1250,6 +1257,8 @@ static struct kfd_process *create_process(const struct task_struct *thread)
err_register_notifier: err_register_notifier:
hash_del_rcu(&process->kfd_processes); hash_del_rcu(&process->kfd_processes);
svm_range_list_fini(process);
err_init_svm_range_list:
kfd_process_free_outstanding_kfd_bos(process); kfd_process_free_outstanding_kfd_bos(process);
kfd_process_destroy_pdds(process); kfd_process_destroy_pdds(process);
err_init_apertures: err_init_apertures:
......
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0 OR MIT */
/*
* Copyright 2020-2021 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
*/
#ifndef KFD_SVM_H_
#define KFD_SVM_H_
#include <linux/rwsem.h>
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/sched/mm.h>
#include <linux/hmm.h>
#include "amdgpu.h"
#include "kfd_priv.h"
/**
* struct svm_range - shared virtual memory range
*
* @svms: list of svm ranges, structure defined in kfd_process
* @start: range start address in pages
* @last: range last address in pages
* @it_node: node [start, last] stored in interval tree, start, last are page
* aligned, page size is (last - start + 1)
* @list: link list node, used to scan all ranges of svms
* @update_list:link list node used to add to update_list
* @remove_list:link list node used to add to remove list
* @insert_list:link list node used to add to insert list
* @npages: number of pages
* @flags: flags defined as KFD_IOCTL_SVM_FLAG_*
* @perferred_loc: perferred location, 0 for CPU, or GPU id
* @perfetch_loc: last prefetch location, 0 for CPU, or GPU id
* @actual_loc: the actual location, 0 for CPU, or GPU id
* @granularity:migration granularity, log2 num pages
* @bitmap_access: index bitmap of GPUs which can access the range
* @bitmap_aip: index bitmap of GPUs which can access the range in place
*
* Data structure for virtual memory range shared by CPU and GPUs, it can be
* allocated from system memory ram or device vram, and migrate from ram to vram
* or from vram to ram.
*/
struct svm_range {
struct svm_range_list *svms;
unsigned long start;
unsigned long last;
struct interval_tree_node it_node;
struct list_head list;
struct list_head update_list;
struct list_head remove_list;
struct list_head insert_list;
uint64_t npages;
uint32_t flags;
uint32_t preferred_loc;
uint32_t prefetch_loc;
uint32_t actual_loc;
uint8_t granularity;
DECLARE_BITMAP(bitmap_access, MAX_GPU_INSTANCE);
DECLARE_BITMAP(bitmap_aip, MAX_GPU_INSTANCE);
};
int svm_range_list_init(struct kfd_process *p);
void svm_range_list_fini(struct kfd_process *p);
int svm_ioctl(struct kfd_process *p, enum kfd_ioctl_svm_op op, uint64_t start,
uint64_t size, uint32_t nattrs,
struct kfd_ioctl_svm_attribute *attrs);
#endif /* KFD_SVM_H_ */
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