Linux-mm Archive on lore.kernel.org
 help / color / Atom feed
From: "Thomas Hellström (VMware)" <thomas_os@shipmail.org>
To: "Christian König" <christian.koenig@amd.com>,
	linux-mm@kvack.org, linux-kernel@vger.kernel.org,
	dri-devel@lists.freedesktop.org
Cc: pv-drivers@vmware.com, linux-graphics-maintainer@vmware.com,
	"Thomas Hellstrom" <thellstrom@vmware.com>,
	"Andrew Morton" <akpm@linux-foundation.org>,
	"Michal Hocko" <mhocko@suse.com>,
	"Matthew Wilcox (Oracle)" <willy@infradead.org>,
	"Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>,
	"Ralph Campbell" <rcampbell@nvidia.com>,
	"Jérôme Glisse" <jglisse@redhat.com>
Subject: Re: [PATCH 6/8] drm: Add a drm_get_unmapped_area() helper
Date: Wed, 4 Dec 2019 12:36:47 +0100
Message-ID: <98af5b11-1034-91fa-aa38-5730f116d1cd@shipmail.org> (raw)
In-Reply-To: <e091063c-2c4a-866e-acdb-9efb1e20d737@amd.com>

On 12/4/19 12:11 PM, Christian König wrote:
> Am 03.12.19 um 14:22 schrieb Thomas Hellström (VMware):
>> From: Thomas Hellstrom <thellstrom@vmware.com>
>>
>> This helper is used to align user-space buffer object addresses to
>> huge page boundaries, minimizing the chance of alignment mismatch
>> between user-space addresses and physical addresses.
>
> Mhm, I'm wondering if that is really such a good idea.

Could you elaborate? What drawbacks do you see?
Note that this is the way other subsystems are doing it. Take a look at 
shmem_get_unmapped_area() for instance.

>
> Wouldn't it be sufficient if userspace uses MAP_HUGETLB?

MAP_HUGETLB is something different and appears to be tied to the kernel 
persistent huge page mechanism, whereas the TTM huge pages is tided to 
the THP functionality (although skipped by khugepaged).

Thanks,

Thomas



>
> Regards,
> Christian.
>
>>
>> Cc: Andrew Morton <akpm@linux-foundation.org>
>> Cc: Michal Hocko <mhocko@suse.com>
>> Cc: "Matthew Wilcox (Oracle)" <willy@infradead.org>
>> Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
>> Cc: Ralph Campbell <rcampbell@nvidia.com>
>> Cc: "Jérôme Glisse" <jglisse@redhat.com>
>> Cc: "Christian König" <christian.koenig@amd.com>
>> Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
>> ---
>>   drivers/gpu/drm/drm_file.c | 130 +++++++++++++++++++++++++++++++++++++
>>   include/drm/drm_file.h     |   5 ++
>>   2 files changed, 135 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c
>> index ea34bc991858..e5b4024cd397 100644
>> --- a/drivers/gpu/drm/drm_file.c
>> +++ b/drivers/gpu/drm/drm_file.c
>> @@ -31,6 +31,8 @@
>>    * OTHER DEALINGS IN THE SOFTWARE.
>>    */
>>   +#include <uapi/asm/mman.h>
>> +
>>   #include <linux/dma-fence.h>
>>   #include <linux/module.h>
>>   #include <linux/pci.h>
>> @@ -41,6 +43,7 @@
>>   #include <drm/drm_drv.h>
>>   #include <drm/drm_file.h>
>>   #include <drm/drm_print.h>
>> +#include <drm/drm_vma_manager.h>
>>     #include "drm_crtc_internal.h"
>>   #include "drm_internal.h"
>> @@ -754,3 +757,130 @@ void drm_send_event(struct drm_device *dev, 
>> struct drm_pending_event *e)
>>       spin_unlock_irqrestore(&dev->event_lock, irqflags);
>>   }
>>   EXPORT_SYMBOL(drm_send_event);
>> +
>> +#ifdef CONFIG_TRANSPARENT_HUGEPAGE
>> +/*
>> + * drm_addr_inflate() attempts to construct an aligned area by 
>> inflating
>> + * the area size and skipping the unaligned start of the area.
>> + * adapted from shmem_get_unmapped_area()
>> + */
>> +static unsigned long drm_addr_inflate(unsigned long addr,
>> +                      unsigned long len,
>> +                      unsigned long pgoff,
>> +                      unsigned long flags,
>> +                      unsigned long huge_size)
>> +{
>> +    unsigned long offset, inflated_len;
>> +    unsigned long inflated_addr;
>> +    unsigned long inflated_offset;
>> +
>> +    offset = (pgoff << PAGE_SHIFT) & (huge_size - 1);
>> +    if (offset && offset + len < 2 * huge_size)
>> +        return addr;
>> +    if ((addr & (huge_size - 1)) == offset)
>> +        return addr;
>> +
>> +    inflated_len = len + huge_size - PAGE_SIZE;
>> +    if (inflated_len > TASK_SIZE)
>> +        return addr;
>> +    if (inflated_len < len)
>> +        return addr;
>> +
>> +    inflated_addr = current->mm->get_unmapped_area(NULL, 0, 
>> inflated_len,
>> +                               0, flags);
>> +    if (IS_ERR_VALUE(inflated_addr))
>> +        return addr;
>> +    if (inflated_addr & ~PAGE_MASK)
>> +        return addr;
>> +
>> +    inflated_offset = inflated_addr & (huge_size - 1);
>> +    inflated_addr += offset - inflated_offset;
>> +    if (inflated_offset > offset)
>> +        inflated_addr += huge_size;
>> +
>> +    if (inflated_addr > TASK_SIZE - len)
>> +        return addr;
>> +
>> +    return inflated_addr;
>> +}
>> +
>> +/**
>> + * drm_get_unmapped_area() - Get an unused user-space virtual memory 
>> area
>> + * suitable for huge page table entries.
>> + * @file: The struct file representing the address space being 
>> mmap()'d.
>> + * @uaddr: Start address suggested by user-space.
>> + * @len: Length of the area.
>> + * @pgoff: The page offset into the address space.
>> + * @flags: mmap flags
>> + * @mgr: The address space manager used by the drm driver. This 
>> argument can
>> + * probably be removed at some point when all drivers use the same
>> + * address space manager.
>> + *
>> + * This function attempts to find an unused user-space virtual 
>> memory area
>> + * that can accommodate the size we want to map, and that is properly
>> + * aligned to facilitate huge page table entries matching actual
>> + * huge pages or huge page aligned memory in buffer objects. Buffer 
>> objects
>> + * are assumed to start at huge page boundary pfns (io memory) or be
>> + * populated by huge pages aligned to the start of the buffer object
>> + * (system- or coherent memory). Adapted from shmem_get_unmapped_area.
>> + *
>> + * Return: aligned user-space address.
>> + */
>> +unsigned long drm_get_unmapped_area(struct file *file,
>> +                    unsigned long uaddr, unsigned long len,
>> +                    unsigned long pgoff, unsigned long flags,
>> +                    struct drm_vma_offset_manager *mgr)
>> +{
>> +    unsigned long addr;
>> +    unsigned long inflated_addr;
>> +    struct drm_vma_offset_node *node;
>> +
>> +    if (len > TASK_SIZE)
>> +        return -ENOMEM;
>> +
>> +    /* Adjust mapping offset to be zero at bo start */
>> +    drm_vma_offset_lock_lookup(mgr);
>> +    node = drm_vma_offset_lookup_locked(mgr, pgoff, 1);
>> +    if (node)
>> +        pgoff -= node->vm_node.start;
>> +    drm_vma_offset_unlock_lookup(mgr);
>> +
>> +    addr = current->mm->get_unmapped_area(file, uaddr, len, pgoff, 
>> flags);
>> +    if (IS_ERR_VALUE(addr))
>> +        return addr;
>> +    if (addr & ~PAGE_MASK)
>> +        return addr;
>> +    if (addr > TASK_SIZE - len)
>> +        return addr;
>> +
>> +    if (len < HPAGE_PMD_SIZE)
>> +        return addr;
>> +    if (flags & MAP_FIXED)
>> +        return addr;
>> +    /*
>> +     * Our priority is to support MAP_SHARED mapped hugely;
>> +     * and support MAP_PRIVATE mapped hugely too, until it is COWed.
>> +     * But if caller specified an address hint, respect that as before.
>> +     */
>> +    if (uaddr)
>> +        return addr;
>> +
>> +    inflated_addr = drm_addr_inflate(addr, len, pgoff, flags,
>> +                     HPAGE_PMD_SIZE);
>> +
>> +    if (IS_ENABLED(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD) &&
>> +        len >= HPAGE_PUD_SIZE)
>> +        inflated_addr = drm_addr_inflate(inflated_addr, len, pgoff,
>> +                         flags, HPAGE_PUD_SIZE);
>> +    return inflated_addr;
>> +}
>> +#else /* CONFIG_TRANSPARENT_HUGEPAGE */
>> +unsigned long drm_get_unmapped_area(struct file *file,
>> +                    unsigned long uaddr, unsigned long len,
>> +                    unsigned long pgoff, unsigned long flags,
>> +                    struct drm_vma_offset_manager *mgr)
>> +{
>> +    return current->mm->get_unmapped_area(file, uaddr, len, pgoff, 
>> flags);
>> +}
>> +#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
>> +EXPORT_SYMBOL_GPL(drm_get_unmapped_area);
>> diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h
>> index 67af60bb527a..4719cc80d547 100644
>> --- a/include/drm/drm_file.h
>> +++ b/include/drm/drm_file.h
>> @@ -386,5 +386,10 @@ void drm_event_cancel_free(struct drm_device *dev,
>>                  struct drm_pending_event *p);
>>   void drm_send_event_locked(struct drm_device *dev, struct 
>> drm_pending_event *e);
>>   void drm_send_event(struct drm_device *dev, struct 
>> drm_pending_event *e);
>> +struct drm_vma_offset_manager;
>> +unsigned long drm_get_unmapped_area(struct file *file,
>> +                    unsigned long uaddr, unsigned long len,
>> +                    unsigned long pgoff, unsigned long flags,
>> +                    struct drm_vma_offset_manager *mgr);
>>     #endif /* _DRM_FILE_H_ */




  reply index

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-12-03 13:22 [PATCH 0/8] Huge page-table entries for TTM Thomas Hellström (VMware)
2019-12-03 13:22 ` [PATCH 1/8] mm: Introduce vma_is_special_huge Thomas Hellström (VMware)
2019-12-03 13:22 ` [PATCH 2/8] mm: Split huge pages on write-notify or COW Thomas Hellström (VMware)
2019-12-03 13:22 ` [PATCH 3/8] mm: Add vmf_insert_pfn_xxx_prot() for huge page-table entries Thomas Hellström (VMware)
2019-12-03 13:22 ` [PATCH 4/8] drm/ttm, drm/vmwgfx: Support huge TTM pagefaults Thomas Hellström (VMware)
2019-12-03 13:22 ` [PATCH 5/8] drm/vmwgfx: Support huge page faults Thomas Hellström (VMware)
2019-12-03 13:22 ` [PATCH 6/8] drm: Add a drm_get_unmapped_area() helper Thomas Hellström (VMware)
2019-12-04 11:11   ` Christian König
2019-12-04 11:36     ` Thomas Hellström (VMware) [this message]
2019-12-04 12:08       ` Christian König
2019-12-04 12:32         ` Thomas Hellström (VMware)
2019-12-04 14:40           ` Christian König
2019-12-04 15:36             ` Thomas Hellström (VMware)
2019-12-03 13:22 ` [PATCH 7/8] drm/ttm: Introduce a huge page aligning TTM range manager Thomas Hellström (VMware)
2019-12-04 11:13   ` Christian König
2019-12-04 11:45     ` Thomas Hellström (VMware)
2019-12-04 12:16       ` Christian König
2019-12-04 13:18         ` Thomas Hellström (VMware)
2019-12-04 14:02           ` Christian König
2019-12-03 13:22 ` [PATCH 8/8] drm/vmwgfx: Hook up the helpers to align buffer objects Thomas Hellström (VMware)

Reply instructions:

You may reply publically to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=98af5b11-1034-91fa-aa38-5730f116d1cd@shipmail.org \
    --to=thomas_os@shipmail.org \
    --cc=akpm@linux-foundation.org \
    --cc=christian.koenig@amd.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=jglisse@redhat.com \
    --cc=kirill.shutemov@linux.intel.com \
    --cc=linux-graphics-maintainer@vmware.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=mhocko@suse.com \
    --cc=pv-drivers@vmware.com \
    --cc=rcampbell@nvidia.com \
    --cc=thellstrom@vmware.com \
    --cc=willy@infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

Linux-mm Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-mm/0 linux-mm/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-mm linux-mm/ https://lore.kernel.org/linux-mm \
		linux-mm@kvack.org
	public-inbox-index linux-mm

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kvack.linux-mm


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git