Re: [PATCH 2/4] drm/amd/amdgpu: add support for iova_to_phys to replace TTM trace (v3)
Am 18.09.2017 um 19:33 schrieb Tom St Denis: Signed-off-by: Tom St Denis(v2): Add domain to iova debugfs (v3): Add true read/write methods to access system memory of pages mapped to the device --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 104 1 file changed, 104 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 50d20903de4f..02ae32378e1c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -43,6 +43,7 @@ #include #include #include +#include #include "amdgpu.h" #include "amdgpu_trace.h" #include "bif/bif_4_1_d.h" @@ -1810,6 +1811,108 @@ static const struct file_operations amdgpu_ttm_gtt_fops = { #endif +static void *transform_page(uint64_t phys) +{ + if (PageHighMem(pfn_to_page(PFN_DOWN(phys + return kmap(pfn_to_page(PFN_DOWN(phys))); + else + return __va(phys); +} + +static void untransform_page(uint64_t phys) +{ + if (PageHighMem(pfn_to_page(PFN_DOWN(phys + return kunmap(pfn_to_page(PFN_DOWN(phys))); +} No need for the extra PageHighMem check, just use kmap()/kunmap() they should do the right thing IIRC. + +static ssize_t amdgpu_iova_to_phys_read(struct file *f, char __user *buf, + size_t size, loff_t *pos) +{ + struct amdgpu_device *adev = file_inode(f)->i_private; + ssize_t result, n; + int r; + uint64_t phys; + void *ptr; + + result = 0; + while (size) { + // get physical address and map + phys = iommu_iova_to_phys(iommu_get_domain_for_dev(adev->dev), *pos); Not sure what iommu_get_domain_for_dev does exactly, but the iommu domain for the device should always be the same so I would call the function only once before the loop. Also failing with -ENODEV here when iommu_get_domain_for_dev() returns NULL sounds like a good idea to me. + + // copy upto one page + if (size > PAGE_SIZE) + n = PAGE_SIZE; + else + n = size; + + // to end of the page + if (((*pos & (PAGE_SIZE - 1)) + n) >= PAGE_SIZE) + n = PAGE_SIZE - (*pos & (PAGE_SIZE - 1)); + + ptr = transform_page(phys); + if (!ptr) + return -EFAULT; + + r = copy_to_user(buf, ptr, n); + untransform_page(phys); + if (r) + return -EFAULT; + + *pos += n; + size -= n; + result += n; + } + + return result; +} + +static ssize_t amdgpu_iova_to_phys_write(struct file *f, const char __user *buf, + size_t size, loff_t *pos) +{ + struct amdgpu_device *adev = file_inode(f)->i_private; + ssize_t result, n; + int r; + uint64_t phys; + void *ptr; + + result = 0; + while (size) { + // get physical address and map + phys = iommu_iova_to_phys(iommu_get_domain_for_dev(adev->dev), *pos); Same comment as above. Apart from that looks good to me, Christian. + + // copy upto one page + if (size > PAGE_SIZE) + n = PAGE_SIZE; + else + n = size; + + // to end of the page + if (((*pos & (PAGE_SIZE - 1)) + n) >= PAGE_SIZE) + n = PAGE_SIZE - (*pos & (PAGE_SIZE - 1)); + + ptr = transform_page(phys); + if (!ptr) + return -EFAULT; + + r = copy_from_user(ptr, buf, n); + untransform_page(phys); + if (r) + return -EFAULT; + + *pos += n; + size -= n; + result += n; + } + + return result; +} + +static const struct file_operations amdgpu_ttm_iova_fops = { + .owner = THIS_MODULE, + .read = amdgpu_iova_to_phys_read, + .write = amdgpu_iova_to_phys_write, + .llseek = default_llseek +}; static const struct { char *name; @@ -1820,6 +1923,7 @@ static const struct { #ifdef CONFIG_DRM_AMDGPU_GART_DEBUGFS { "amdgpu_gtt", _ttm_gtt_fops, TTM_PL_TT }, #endif + { "amdgpu_iova", _ttm_iova_fops, TTM_PL_SYSTEM }, }; #endif ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 2/4] drm/amd/amdgpu: add support for iova_to_phys to replace TTM trace (v3)
Signed-off-by: Tom St Denis(v2): Add domain to iova debugfs (v3): Add true read/write methods to access system memory of pages mapped to the device --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 104 1 file changed, 104 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 50d20903de4f..02ae32378e1c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -43,6 +43,7 @@ #include #include #include +#include #include "amdgpu.h" #include "amdgpu_trace.h" #include "bif/bif_4_1_d.h" @@ -1810,6 +1811,108 @@ static const struct file_operations amdgpu_ttm_gtt_fops = { #endif +static void *transform_page(uint64_t phys) +{ + if (PageHighMem(pfn_to_page(PFN_DOWN(phys + return kmap(pfn_to_page(PFN_DOWN(phys))); + else + return __va(phys); +} + +static void untransform_page(uint64_t phys) +{ + if (PageHighMem(pfn_to_page(PFN_DOWN(phys + return kunmap(pfn_to_page(PFN_DOWN(phys))); +} + +static ssize_t amdgpu_iova_to_phys_read(struct file *f, char __user *buf, + size_t size, loff_t *pos) +{ + struct amdgpu_device *adev = file_inode(f)->i_private; + ssize_t result, n; + int r; + uint64_t phys; + void *ptr; + + result = 0; + while (size) { + // get physical address and map + phys = iommu_iova_to_phys(iommu_get_domain_for_dev(adev->dev), *pos); + + // copy upto one page + if (size > PAGE_SIZE) + n = PAGE_SIZE; + else + n = size; + + // to end of the page + if (((*pos & (PAGE_SIZE - 1)) + n) >= PAGE_SIZE) + n = PAGE_SIZE - (*pos & (PAGE_SIZE - 1)); + + ptr = transform_page(phys); + if (!ptr) + return -EFAULT; + + r = copy_to_user(buf, ptr, n); + untransform_page(phys); + if (r) + return -EFAULT; + + *pos += n; + size -= n; + result += n; + } + + return result; +} + +static ssize_t amdgpu_iova_to_phys_write(struct file *f, const char __user *buf, + size_t size, loff_t *pos) +{ + struct amdgpu_device *adev = file_inode(f)->i_private; + ssize_t result, n; + int r; + uint64_t phys; + void *ptr; + + result = 0; + while (size) { + // get physical address and map + phys = iommu_iova_to_phys(iommu_get_domain_for_dev(adev->dev), *pos); + + // copy upto one page + if (size > PAGE_SIZE) + n = PAGE_SIZE; + else + n = size; + + // to end of the page + if (((*pos & (PAGE_SIZE - 1)) + n) >= PAGE_SIZE) + n = PAGE_SIZE - (*pos & (PAGE_SIZE - 1)); + + ptr = transform_page(phys); + if (!ptr) + return -EFAULT; + + r = copy_from_user(ptr, buf, n); + untransform_page(phys); + if (r) + return -EFAULT; + + *pos += n; + size -= n; + result += n; + } + + return result; +} + +static const struct file_operations amdgpu_ttm_iova_fops = { + .owner = THIS_MODULE, + .read = amdgpu_iova_to_phys_read, + .write = amdgpu_iova_to_phys_write, + .llseek = default_llseek +}; static const struct { char *name; @@ -1820,6 +1923,7 @@ static const struct { #ifdef CONFIG_DRM_AMDGPU_GART_DEBUGFS { "amdgpu_gtt", _ttm_gtt_fops, TTM_PL_TT }, #endif + { "amdgpu_iova", _ttm_iova_fops, TTM_PL_SYSTEM }, }; #endif -- 2.12.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 2/4] drm/amd/amdgpu: add support for iova_to_phys to replace TTM trace
On 18/09/17 08:52 AM, Christian König wrote: Am 18.09.2017 um 14:35 schrieb Tom St Denis: Signed-off-by: Tom St Denis--- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 32 1 file changed, 32 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 7848ffa99eb4..b4c298925e2a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -43,6 +43,7 @@ #include #include #include +#include #include "amdgpu.h" #include "amdgpu_trace.h" #include "bif/bif_4_1_d.h" @@ -1810,6 +1811,36 @@ static const struct file_operations amdgpu_ttm_gtt_fops = { #endif +static ssize_t amdgpu_iova_to_phys_read(struct file *f, char __user *buf, + size_t size, loff_t *pos) +{ + struct amdgpu_device *adev = file_inode(f)->i_private; + int r; + uint64_t phys; + + // always return 8 bytes + if (size != 8) + return -EINVAL; + + // only accept page addresses + if (*pos & 0xFFF) + return -EINVAL; + + + phys = iommu_iova_to_phys(iommu_get_domain_for_dev(adev->dev), *pos); Well how about adding directly read/write support for the page behind the address? This way we won't need to fiddle with /dev/mem any more either. Given the flak we got from requesting this from the iommu team I'm worried that might not be appreciated by the community (even though we maintain this part of the tree) and hurt our abilities to upstream. I agree that adding a read/write method would be better though since we don't need config changes of /dev/fmem anymore. Tom ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 2/4] drm/amd/amdgpu: add support for iova_to_phys to replace TTM trace
Am 18.09.2017 um 14:35 schrieb Tom St Denis: Signed-off-by: Tom St Denis--- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 32 1 file changed, 32 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 7848ffa99eb4..b4c298925e2a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -43,6 +43,7 @@ #include #include #include +#include #include "amdgpu.h" #include "amdgpu_trace.h" #include "bif/bif_4_1_d.h" @@ -1810,6 +1811,36 @@ static const struct file_operations amdgpu_ttm_gtt_fops = { #endif +static ssize_t amdgpu_iova_to_phys_read(struct file *f, char __user *buf, + size_t size, loff_t *pos) +{ + struct amdgpu_device *adev = file_inode(f)->i_private; + int r; + uint64_t phys; + + // always return 8 bytes + if (size != 8) + return -EINVAL; + + // only accept page addresses + if (*pos & 0xFFF) + return -EINVAL; + + + phys = iommu_iova_to_phys(iommu_get_domain_for_dev(adev->dev), *pos); Well how about adding directly read/write support for the page behind the address? This way we won't need to fiddle with /dev/mem any more either. Christian. + + r = copy_to_user(buf, , 8); + if (r) + return -EFAULT; + + return 8; +} + +static const struct file_operations amdgpu_ttm_iova_fops = { + .owner = THIS_MODULE, + .read = amdgpu_iova_to_phys_read, + .llseek = default_llseek +}; static const struct { char *name; @@ -1819,6 +1850,7 @@ static const struct { #ifdef CONFIG_DRM_AMDGPU_GART_DEBUGFS { "amdgpu_gtt", _ttm_gtt_fops }, #endif + { "amdgpu_iova", _ttm_iova_fops }, }; #endif ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 2/4] drm/amd/amdgpu: add support for iova_to_phys to replace TTM trace
Signed-off-by: Tom St Denis--- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 32 1 file changed, 32 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 7848ffa99eb4..b4c298925e2a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -43,6 +43,7 @@ #include #include #include +#include #include "amdgpu.h" #include "amdgpu_trace.h" #include "bif/bif_4_1_d.h" @@ -1810,6 +1811,36 @@ static const struct file_operations amdgpu_ttm_gtt_fops = { #endif +static ssize_t amdgpu_iova_to_phys_read(struct file *f, char __user *buf, + size_t size, loff_t *pos) +{ + struct amdgpu_device *adev = file_inode(f)->i_private; + int r; + uint64_t phys; + + // always return 8 bytes + if (size != 8) + return -EINVAL; + + // only accept page addresses + if (*pos & 0xFFF) + return -EINVAL; + + + phys = iommu_iova_to_phys(iommu_get_domain_for_dev(adev->dev), *pos); + + r = copy_to_user(buf, , 8); + if (r) + return -EFAULT; + + return 8; +} + +static const struct file_operations amdgpu_ttm_iova_fops = { + .owner = THIS_MODULE, + .read = amdgpu_iova_to_phys_read, + .llseek = default_llseek +}; static const struct { char *name; @@ -1819,6 +1850,7 @@ static const struct { #ifdef CONFIG_DRM_AMDGPU_GART_DEBUGFS { "amdgpu_gtt", _ttm_gtt_fops }, #endif + { "amdgpu_iova", _ttm_iova_fops }, }; #endif -- 2.12.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel