[PATCH 2/9] drm/amdgpu: Add PASID management

zhoucm1 david1.zhou at amd.com
Mon Aug 28 07:15:23 UTC 2017



On 2017年08月28日 14:45, Christian König wrote:
> I agree that the VM code is growing a bit to much. but the crux is it 
> is very close to VMID management, so we should keep the code together.
>
> I wanted to avoid it, but you suggested to separate the VMID 
> management quite a while ago. How about moving both VMID as well as 
> PASSID into amdgpu_hwid_mgr.c?
If let me choose, I will prefer one is amdgpu_vmid.c, and one is 
amdgpu_pasid.c. :)
Anyway, I have no strong opinion on that, depend on your guys like.

Cheers,
David Zhou
>
> Regards,
> Christian.
>
> Am 28.08.2017 um 05:06 schrieb zhoucm1:
>> Could we separate PASID manager to a clean file like amdgpu_pasid.c 
>> like what context manager done?
>>
>> Since VM code is growing, and which looks more and more complex.
>>
>> btw: really like many comments about PASID explaination. :)
>>
>> Regards,
>> David Zhou
>> On 2017年08月26日 15:19, Felix Kuehling wrote:
>>> Allows assigning a PASID to a VM for identifying VMs involved in page
>>> faults. The global PASID manager is also exported in the KFD
>>> interface so that AMDGPU and KFD can share the PASID space.
>>>
>>> PASIDs of different sizes can be requested. On APUs, the PASID size
>>> is deterined by the capabilities of the IOMMU. So KFD must be able
>>> to allocate PASIDs in a smaller range.
>>>
>>> TODO:
>>> * Actually assign PASIDs to VMs
>>> * Update the PASID-VMID mapping registers during CS
>>>
>>> Change-Id: I88c9357a7c584f10e84b5607ac09eba77c833393
>>> Signed-off-by: Felix Kuehling <Felix.Kuehling at amd.com>
>>> ---
>>>   drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c |  2 +
>>>   drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c |  2 +
>>>   drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c |  2 +
>>>   drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c  |  2 +-
>>>   drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c           |  2 +-
>>>   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c            | 76 
>>> ++++++++++++++++++++++-
>>>   drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h            | 14 ++++-
>>>   drivers/gpu/drm/amd/include/kgd_kfd_interface.h   |  6 ++
>>>   8 files changed, 101 insertions(+), 5 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c 
>>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c
>>> index 3e28d2b..0807d52 100644
>>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c
>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c
>>> @@ -188,6 +188,8 @@ static const struct kfd2kgd_calls kfd2kgd = {
>>>       .get_local_mem_info = get_local_mem_info,
>>>       .get_gpu_clock_counter = get_gpu_clock_counter,
>>>       .get_max_engine_clock_in_mhz = get_max_engine_clock_in_mhz,
>>> +    .alloc_pasid = amdgpu_vm_alloc_pasid,
>>> +    .free_pasid = amdgpu_vm_free_pasid,
>>>       .create_process_vm = amdgpu_amdkfd_gpuvm_create_process_vm,
>>>       .destroy_process_vm = amdgpu_amdkfd_gpuvm_destroy_process_vm,
>>>       .get_process_page_dir = amdgpu_amdkfd_gpuvm_get_process_page_dir,
>>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c 
>>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c
>>> index 3b6b4d9..c20c000 100644
>>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c
>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c
>>> @@ -162,6 +162,8 @@ static const struct kfd2kgd_calls kfd2kgd = {
>>>       .get_local_mem_info = get_local_mem_info,
>>>       .get_gpu_clock_counter = get_gpu_clock_counter,
>>>       .get_max_engine_clock_in_mhz = get_max_engine_clock_in_mhz,
>>> +    .alloc_pasid = amdgpu_vm_alloc_pasid,
>>> +    .free_pasid = amdgpu_vm_free_pasid,
>>>       .create_process_vm = amdgpu_amdkfd_gpuvm_create_process_vm,
>>>       .destroy_process_vm = amdgpu_amdkfd_gpuvm_destroy_process_vm,
>>>       .create_process_gpumem = create_process_gpumem,
>>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c 
>>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c
>>> index 961369d..bb99c64 100644
>>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c
>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c
>>> @@ -209,6 +209,8 @@ static const struct kfd2kgd_calls kfd2kgd = {
>>>       .get_local_mem_info = get_local_mem_info,
>>>       .get_gpu_clock_counter = get_gpu_clock_counter,
>>>       .get_max_engine_clock_in_mhz = get_max_engine_clock_in_mhz,
>>> +    .alloc_pasid = amdgpu_vm_alloc_pasid,
>>> +    .free_pasid = amdgpu_vm_free_pasid,
>>>       .create_process_vm = amdgpu_amdkfd_gpuvm_create_process_vm,
>>>       .destroy_process_vm = amdgpu_amdkfd_gpuvm_destroy_process_vm,
>>>       .create_process_gpumem = create_process_gpumem,
>>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c 
>>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
>>> index 35f7d77..462011c 100644
>>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
>>> @@ -1397,7 +1397,7 @@ int 
>>> amdgpu_amdkfd_gpuvm_create_process_vm(struct kgd_dev *kgd, void **vm,
>>>           return -ENOMEM;
>>>         /* Initialize the VM context, allocate the page directory 
>>> and zero it */
>>> -    ret = amdgpu_vm_init(adev, &new_vm->base, 
>>> AMDGPU_VM_CONTEXT_COMPUTE);
>>> +    ret = amdgpu_vm_init(adev, &new_vm->base, 
>>> AMDGPU_VM_CONTEXT_COMPUTE, 0);
>>>       if (ret != 0) {
>>>           pr_err("Failed init vm ret %d\n", ret);
>>>           /* Undo everything related to the new VM context */
>>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c 
>>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
>>> index e390c01..ba3dc4d 100644
>>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
>>> @@ -825,7 +825,7 @@ int amdgpu_driver_open_kms(struct drm_device 
>>> *dev, struct drm_file *file_priv)
>>>       }
>>>         r = amdgpu_vm_init(adev, &fpriv->vm,
>>> -               AMDGPU_VM_CONTEXT_GFX);
>>> +               AMDGPU_VM_CONTEXT_GFX, 0);
>>>       if (r) {
>>>           kfree(fpriv);
>>>           goto out_suspend;
>>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c 
>>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
>>> index 70d7632..c635699 100644
>>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
>>> @@ -27,12 +27,59 @@
>>>    */
>>>   #include <linux/dma-fence-array.h>
>>>   #include <linux/interval_tree_generic.h>
>>> +#include <linux/idr.h>
>>>   #include <drm/drmP.h>
>>>   #include <drm/amdgpu_drm.h>
>>>   #include "amdgpu.h"
>>>   #include "amdgpu_trace.h"
>>>     /*
>>> + * PASID manager
>>> + *
>>> + * PASIDs are global address space identifiers that can be shared
>>> + * between the GPU, an IOMMU and the driver. VMs on different devices
>>> + * may use the same PASID if they share the same address
>>> + * space. Therefore PASIDs are allocated using a global IDA. VMs are
>>> + * looked up from the PASID per amdgpu_device.
>>> + */
>>> +static DEFINE_IDA(amdgpu_vm_pasid_ida);
>>> +
>>> +/**
>>> + * amdgpu_vm_alloc_pasid - Allocate a PASID
>>> + * @bits: Maximum width of the PASID in bits, must be at least 1
>>> + *
>>> + * Allocates a PASID of the given width while keeping smaller PASIDs
>>> + * available if possible.
>>> + *
>>> + * Returns a positive integer on success. Returns %-EINVAL if bits==0.
>>> + * Returns %-ENOSPC if no PASID was avaliable. Returns %-ENOMEM on
>>> + * memory allocation failure.
>>> + */
>>> +int amdgpu_vm_alloc_pasid(unsigned int bits)
>>> +{
>>> +    int pasid = -EINVAL;
>>> +
>>> +    for (bits = min(bits, 31U); bits > 0; bits--) {
>>> +        pasid = ida_simple_get(&amdgpu_vm_pasid_ida,
>>> +                       1U << (bits - 1), 1U << bits,
>>> +                       GFP_KERNEL);
>>> +        if (pasid != -ENOSPC)
>>> +            break;
>>> +    }
>>> +
>>> +    return pasid;
>>> +}
>>> +
>>> +/**
>>> + * amdgpu_vm_free_pasid - Free a PASID
>>> + * @pasid: PASID to free
>>> + */
>>> +void amdgpu_vm_free_pasid(unsigned int pasid)
>>> +{
>>> +    ida_simple_remove(&amdgpu_vm_pasid_ida, pasid);
>>> +}
>>> +
>>> +/*
>>>    * GPUVM
>>>    * GPUVM is similar to the legacy gart on older asics, however
>>>    * rather than there being a single global gart table
>>> @@ -2482,7 +2529,7 @@ void amdgpu_vm_adjust_size(struct 
>>> amdgpu_device *adev, uint64_t vm_size, uint32_
>>>    * Init @vm fields.
>>>    */
>>>   int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm,
>>> -           int vm_context)
>>> +           int vm_context, unsigned int pasid)
>>>   {
>>>       const unsigned align = min(AMDGPU_VM_PTB_ALIGN_SIZE,
>>>           AMDGPU_VM_PTE_COUNT(adev) * 8);
>>> @@ -2562,6 +2609,19 @@ int amdgpu_vm_init(struct amdgpu_device 
>>> *adev, struct amdgpu_vm *vm,
>>>       if (r)
>>>           goto error_free_root;
>>>   +    if (pasid) {
>>> +        unsigned long flags;
>>> +
>>> + spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags);
>>> +        r = idr_alloc(&adev->vm_manager.pasid_idr, vm, pasid, pasid 
>>> + 1,
>>> +                  GFP_ATOMIC);
>>> + spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags);
>>> +        if (r < 0)
>>> +            goto error_free_root;
>>> +
>>> +        vm->pasid = pasid;
>>> +    }
>>> +
>>>       vm->vm_context = vm_context;
>>>       if (vm_context == AMDGPU_VM_CONTEXT_COMPUTE) {
>>>           mutex_lock(&id_mgr->lock);
>>> @@ -2650,6 +2710,14 @@ void amdgpu_vm_fini(struct amdgpu_device 
>>> *adev, struct amdgpu_vm *vm)
>>>           mutex_unlock(&id_mgr->lock);
>>>       }
>>>   +    if (vm->pasid) {
>>> +        unsigned long flags;
>>> +
>>> + spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags);
>>> +        idr_remove(&adev->vm_manager.pasid_idr, vm->pasid);
>>> + spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags);
>>> +    }
>>> +
>>>       amd_sched_entity_fini(vm->entity.sched, &vm->entity);
>>>         if (!RB_EMPTY_ROOT(&vm->va)) {
>>> @@ -2729,6 +2797,9 @@ void amdgpu_vm_manager_init(struct 
>>> amdgpu_device *adev)
>>>       adev->vm_manager.vm_update_mode = 0;
>>>   #endif
>>>   +    idr_init(&adev->vm_manager.pasid_idr);
>>> +    spin_lock_init(&adev->vm_manager.pasid_lock);
>>> +
>>>       adev->vm_manager.n_compute_vms = 0;
>>>   }
>>>   @@ -2743,6 +2814,9 @@ void amdgpu_vm_manager_fini(struct 
>>> amdgpu_device *adev)
>>>   {
>>>       unsigned i, j;
>>>   + WARN_ON(!idr_is_empty(&adev->vm_manager.pasid_idr));
>>> +    idr_destroy(&adev->vm_manager.pasid_idr);
>>> +
>>>       for (i = 0; i < AMDGPU_MAX_VMHUBS; ++i) {
>>>           struct amdgpu_vm_id_manager *id_mgr =
>>>               &adev->vm_manager.id_mgr[i];
>>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h 
>>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
>>> index 49e15d7..692b05c 100644
>>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
>>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
>>> @@ -25,6 +25,7 @@
>>>   #define __AMDGPU_VM_H__
>>>     #include <linux/rbtree.h>
>>> +#include <linux/idr.h>
>>>     #include "gpu_scheduler.h"
>>>   #include "amdgpu_sync.h"
>>> @@ -143,8 +144,9 @@ struct amdgpu_vm {
>>>       /* Scheduler entity for page table updates */
>>>       struct amd_sched_entity    entity;
>>>   -    /* client id */
>>> +    /* client id and PASID (TODO: replace client_id with PASID) */
>>>       u64                     client_id;
>>> +    unsigned int        pasid;
>>>       /* dedicated to vm */
>>>       struct amdgpu_vm_id *reserved_vmid[AMDGPU_MAX_VMHUBS];
>>>   @@ -219,14 +221,22 @@ struct amdgpu_vm_manager {
>>>        */
>>>       int                    vm_update_mode;
>>>   +    /* PASID to VM mapping, will be used in interrupt context to
>>> +     * look up VM of a page fault
>>> +     */
>>> +    struct idr                pasid_idr;
>>> +    spinlock_t                pasid_lock;
>>> +
>>>       /* Number of Compute VMs, used for detecting Compute activity */
>>>       unsigned                                n_compute_vms;
>>>   };
>>>   +int amdgpu_vm_alloc_pasid(unsigned int bits);
>>> +void amdgpu_vm_free_pasid(unsigned int pasid);
>>>   void amdgpu_vm_manager_init(struct amdgpu_device *adev);
>>>   void amdgpu_vm_manager_fini(struct amdgpu_device *adev);
>>>   int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm,
>>> -           int vm_context);
>>> +           int vm_context, unsigned int pasid);
>>>   void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm 
>>> *vm);
>>>   void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm,
>>>                struct list_head *validated,
>>> diff --git a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h 
>>> b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h
>>> index e8027b3..5833ef7 100644
>>> --- a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h
>>> +++ b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h
>>> @@ -188,6 +188,9 @@ struct tile_config {
>>>    *
>>>    * @get_max_engine_clock_in_mhz: Retrieves maximum GPU clock in MHz
>>>    *
>>> + * @alloc_pasid: Allocate a PASID
>>> + * @free_pasid: Free a PASID
>>> + *
>>>    * @program_sh_mem_settings: A function that should initiate the 
>>> memory
>>>    * properties such as main aperture memory type (cache / non 
>>> cached) and
>>>    * secondary aperture base address, size and memory type.
>>> @@ -264,6 +267,9 @@ struct kfd2kgd_calls {
>>>         uint32_t (*get_max_engine_clock_in_mhz)(struct kgd_dev *kgd);
>>>   +    int (*alloc_pasid)(unsigned int bits);
>>> +    void (*free_pasid)(unsigned int pasid);
>>> +
>>>       int (*create_process_vm)(struct kgd_dev *kgd, void **vm,
>>>                    void **process_info);
>>>       void (*destroy_process_vm)(struct kgd_dev *kgd, void *vm);
>>
>> _______________________________________________
>> amd-gfx mailing list
>> amd-gfx at lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
>
>



More information about the amd-gfx mailing list