2019-03-19 02:20:35

by Souptick Joarder

[permalink] [raw]
Subject: [RESEND PATCH v4 0/9] mm: Use vm_map_pages() and vm_map_pages_zero() API

Previouly drivers have their own way of mapping range of
kernel pages/memory into user vma and this was done by
invoking vm_insert_page() within a loop.

As this pattern is common across different drivers, it can
be generalized by creating new functions and use it across
the drivers.

vm_map_pages() is the API which could be used to map
kernel memory/pages in drivers which has considered vm_pgoff.

vm_map_pages_zero() is the API which could be used to map
range of kernel memory/pages in drivers which has not considered
vm_pgoff. vm_pgoff is passed default as 0 for those drivers.

We _could_ then at a later "fix" these drivers which are using
vm_map_pages_zero() to behave according to the normal vm_pgoff
offsetting simply by removing the _zero suffix on the function
name and if that causes regressions, it gives us an easy way to revert.

Tested on Rockchip hardware and display is working fine, including talking
to Lima via prime.

v1 -> v2:
Few Reviewed-by.

Updated the change log in [8/9]

In [7/9], vm_pgoff is treated in V4L2 API as a 'cookie'
to select a buffer, not as a in-buffer offset by design
and it always want to mmap a whole buffer from its beginning.
Added additional changes after discussing with Marek and
vm_map_pages() could be used instead of vm_map_pages_zero().

v2 -> v3:
Corrected the documentation as per review comment.

As suggested in v2, renaming the interfaces to -
*vm_insert_range() -> vm_map_pages()* and
*vm_insert_range_buggy() -> vm_map_pages_zero()*.
As the interface is renamed, modified the code accordingly,
updated the change logs and modified the subject lines to use the
new interfaces. There is no other change apart from renaming and
using the new interface.

Patch[1/9] & [4/9], Tested on Rockchip hardware.

v3 -> v4:
Fixed build warnings on patch [8/9] reported by kbuild test robot.

Souptick Joarder (9):
mm: Introduce new vm_map_pages() and vm_map_pages_zero() API
arm: mm: dma-mapping: Convert to use vm_map_pages()
drivers/firewire/core-iso.c: Convert to use vm_map_pages_zero()
drm/rockchip/rockchip_drm_gem.c: Convert to use vm_map_pages()
drm/xen/xen_drm_front_gem.c: Convert to use vm_map_pages()
iommu/dma-iommu.c: Convert to use vm_map_pages()
videobuf2/videobuf2-dma-sg.c: Convert to use vm_map_pages()
xen/gntdev.c: Convert to use vm_map_pages()
xen/privcmd-buf.c: Convert to use vm_map_pages_zero()

arch/arm/mm/dma-mapping.c | 22 ++----
drivers/firewire/core-iso.c | 15 +---
drivers/gpu/drm/rockchip/rockchip_drm_gem.c | 17 +----
drivers/gpu/drm/xen/xen_drm_front_gem.c | 18 ++---
drivers/iommu/dma-iommu.c | 12 +---
drivers/media/common/videobuf2/videobuf2-core.c | 7 ++
.../media/common/videobuf2/videobuf2-dma-contig.c | 6 --
drivers/media/common/videobuf2/videobuf2-dma-sg.c | 22 ++----
drivers/xen/gntdev.c | 11 ++-
drivers/xen/privcmd-buf.c | 8 +--
include/linux/mm.h | 4 ++
mm/memory.c | 81 ++++++++++++++++++++++
mm/nommu.c | 14 ++++
13 files changed, 134 insertions(+), 103 deletions(-)

--
1.9.1



2019-03-19 02:20:40

by Souptick Joarder

[permalink] [raw]
Subject: [RESEND PATCH v4 1/9] mm: Introduce new vm_map_pages() and vm_map_pages_zero() API

Previouly drivers have their own way of mapping range of
kernel pages/memory into user vma and this was done by
invoking vm_insert_page() within a loop.

As this pattern is common across different drivers, it can
be generalized by creating new functions and use it across
the drivers.

vm_map_pages() is the API which could be used to mapped
kernel memory/pages in drivers which has considered vm_pgoff

vm_map_pages_zero() is the API which could be used to map
range of kernel memory/pages in drivers which has not considered
vm_pgoff. vm_pgoff is passed default as 0 for those drivers.

We _could_ then at a later "fix" these drivers which are using
vm_map_pages_zero() to behave according to the normal vm_pgoff
offsetting simply by removing the _zero suffix on the function
name and if that causes regressions, it gives us an easy way to revert.

Tested on Rockchip hardware and display is working, including talking
to Lima via prime.

Signed-off-by: Souptick Joarder <[email protected]>
Suggested-by: Russell King <[email protected]>
Suggested-by: Matthew Wilcox <[email protected]>
Reviewed-by: Mike Rapoport <[email protected]>
Tested-by: Heiko Stuebner <[email protected]>
---
include/linux/mm.h | 4 +++
mm/memory.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
mm/nommu.c | 14 ++++++++++
3 files changed, 99 insertions(+)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index 80bb640..e0aaa73 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2565,6 +2565,10 @@ unsigned long change_prot_numa(struct vm_area_struct *vma,
int remap_pfn_range(struct vm_area_struct *, unsigned long addr,
unsigned long pfn, unsigned long size, pgprot_t);
int vm_insert_page(struct vm_area_struct *, unsigned long addr, struct page *);
+int vm_map_pages(struct vm_area_struct *vma, struct page **pages,
+ unsigned long num);
+int vm_map_pages_zero(struct vm_area_struct *vma, struct page **pages,
+ unsigned long num);
vm_fault_t vmf_insert_pfn(struct vm_area_struct *vma, unsigned long addr,
unsigned long pfn);
vm_fault_t vmf_insert_pfn_prot(struct vm_area_struct *vma, unsigned long addr,
diff --git a/mm/memory.c b/mm/memory.c
index e11ca9d..cad3e27 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1520,6 +1520,87 @@ int vm_insert_page(struct vm_area_struct *vma, unsigned long addr,
}
EXPORT_SYMBOL(vm_insert_page);

+/*
+ * __vm_map_pages - maps range of kernel pages into user vma
+ * @vma: user vma to map to
+ * @pages: pointer to array of source kernel pages
+ * @num: number of pages in page array
+ * @offset: user's requested vm_pgoff
+ *
+ * This allows drivers to map range of kernel pages into a user vma.
+ *
+ * Return: 0 on success and error code otherwise.
+ */
+static int __vm_map_pages(struct vm_area_struct *vma, struct page **pages,
+ unsigned long num, unsigned long offset)
+{
+ unsigned long count = vma_pages(vma);
+ unsigned long uaddr = vma->vm_start;
+ int ret, i;
+
+ /* Fail if the user requested offset is beyond the end of the object */
+ if (offset > num)
+ return -ENXIO;
+
+ /* Fail if the user requested size exceeds available object size */
+ if (count > num - offset)
+ return -ENXIO;
+
+ for (i = 0; i < count; i++) {
+ ret = vm_insert_page(vma, uaddr, pages[offset + i]);
+ if (ret < 0)
+ return ret;
+ uaddr += PAGE_SIZE;
+ }
+
+ return 0;
+}
+
+/**
+ * vm_map_pages - maps range of kernel pages starts with non zero offset
+ * @vma: user vma to map to
+ * @pages: pointer to array of source kernel pages
+ * @num: number of pages in page array
+ *
+ * Maps an object consisting of @num pages, catering for the user's
+ * requested vm_pgoff
+ *
+ * If we fail to insert any page into the vma, the function will return
+ * immediately leaving any previously inserted pages present. Callers
+ * from the mmap handler may immediately return the error as their caller
+ * will destroy the vma, removing any successfully inserted pages. Other
+ * callers should make their own arrangements for calling unmap_region().
+ *
+ * Context: Process context. Called by mmap handlers.
+ * Return: 0 on success and error code otherwise.
+ */
+int vm_map_pages(struct vm_area_struct *vma, struct page **pages,
+ unsigned long num)
+{
+ return __vm_map_pages(vma, pages, num, vma->vm_pgoff);
+}
+EXPORT_SYMBOL(vm_map_pages);
+
+/**
+ * vm_map_pages_zero - map range of kernel pages starts with zero offset
+ * @vma: user vma to map to
+ * @pages: pointer to array of source kernel pages
+ * @num: number of pages in page array
+ *
+ * Similar to vm_map_pages(), except that it explicitly sets the offset
+ * to 0. This function is intended for the drivers that did not consider
+ * vm_pgoff.
+ *
+ * Context: Process context. Called by mmap handlers.
+ * Return: 0 on success and error code otherwise.
+ */
+int vm_map_pages_zero(struct vm_area_struct *vma, struct page **pages,
+ unsigned long num)
+{
+ return __vm_map_pages(vma, pages, num, 0);
+}
+EXPORT_SYMBOL(vm_map_pages_zero);
+
static vm_fault_t insert_pfn(struct vm_area_struct *vma, unsigned long addr,
pfn_t pfn, pgprot_t prot, bool mkwrite)
{
diff --git a/mm/nommu.c b/mm/nommu.c
index 749276b..b492fd1 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -473,6 +473,20 @@ int vm_insert_page(struct vm_area_struct *vma, unsigned long addr,
}
EXPORT_SYMBOL(vm_insert_page);

+int vm_map_pages(struct vm_area_struct *vma, struct page **pages,
+ unsigned long num)
+{
+ return -EINVAL;
+}
+EXPORT_SYMBOL(vm_map_pages);
+
+int vm_map_pages_zero(struct vm_area_struct *vma, struct page **pages,
+ unsigned long num)
+{
+ return -EINVAL;
+}
+EXPORT_SYMBOL(vm_map_pages_zero);
+
/*
* sys_brk() for the most part doesn't need the global kernel
* lock, except when an application is doing something nasty
--
1.9.1


2019-03-19 02:21:29

by Souptick Joarder

[permalink] [raw]
Subject: [RESEND PATCH v4 2/9] arm: mm: dma-mapping: Convert to use vm_map_pages()

Convert to use vm_map_pages() to map range of kernel
memory to user vma.

Signed-off-by: Souptick Joarder <[email protected]>
---
arch/arm/mm/dma-mapping.c | 22 ++++++----------------
1 file changed, 6 insertions(+), 16 deletions(-)

diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index f1e2922..de7c76e 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -1575,31 +1575,21 @@ static int __arm_iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma
void *cpu_addr, dma_addr_t dma_addr, size_t size,
unsigned long attrs)
{
- unsigned long uaddr = vma->vm_start;
- unsigned long usize = vma->vm_end - vma->vm_start;
struct page **pages = __iommu_get_pages(cpu_addr, attrs);
unsigned long nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
- unsigned long off = vma->vm_pgoff;
+ int err;

if (!pages)
return -ENXIO;

- if (off >= nr_pages || (usize >> PAGE_SHIFT) > nr_pages - off)
+ if (vma->vm_pgoff >= nr_pages)
return -ENXIO;

- pages += off;
-
- do {
- int ret = vm_insert_page(vma, uaddr, *pages++);
- if (ret) {
- pr_err("Remapping memory failed: %d\n", ret);
- return ret;
- }
- uaddr += PAGE_SIZE;
- usize -= PAGE_SIZE;
- } while (usize > 0);
+ err = vm_map_pages(vma, pages, nr_pages);
+ if (err)
+ pr_err("Remapping memory failed: %d\n", err);

- return 0;
+ return err;
}
static int arm_iommu_mmap_attrs(struct device *dev,
struct vm_area_struct *vma, void *cpu_addr,
--
1.9.1


2019-03-19 02:23:15

by Souptick Joarder

[permalink] [raw]
Subject: [RESEND PATCH v4 3/9] drivers/firewire/core-iso.c: Convert to use vm_map_pages_zero()

Convert to use vm_map_pages_zero() to map range of kernel memory
to user vma.

This driver has ignored vm_pgoff and mapped the entire pages. We
could later "fix" these drivers to behave according to the normal
vm_pgoff offsetting simply by removing the _zero suffix on the
function name and if that causes regressions, it gives us an easy
way to revert.

Signed-off-by: Souptick Joarder <[email protected]>
---
drivers/firewire/core-iso.c | 15 ++-------------
1 file changed, 2 insertions(+), 13 deletions(-)

diff --git a/drivers/firewire/core-iso.c b/drivers/firewire/core-iso.c
index 35e784c..5414eb1 100644
--- a/drivers/firewire/core-iso.c
+++ b/drivers/firewire/core-iso.c
@@ -107,19 +107,8 @@ int fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card,
int fw_iso_buffer_map_vma(struct fw_iso_buffer *buffer,
struct vm_area_struct *vma)
{
- unsigned long uaddr;
- int i, err;
-
- uaddr = vma->vm_start;
- for (i = 0; i < buffer->page_count; i++) {
- err = vm_insert_page(vma, uaddr, buffer->pages[i]);
- if (err)
- return err;
-
- uaddr += PAGE_SIZE;
- }
-
- return 0;
+ return vm_map_pages_zero(vma, buffer->pages,
+ buffer->page_count);
}

void fw_iso_buffer_destroy(struct fw_iso_buffer *buffer,
--
1.9.1


2019-03-19 02:24:05

by Souptick Joarder

[permalink] [raw]
Subject: [RESEND PATCH v4 5/9] drm/xen/xen_drm_front_gem.c: Convert to use vm_map_pages()

Convert to use vm_map_pages() to map range of kernel
memory to user vma.

Signed-off-by: Souptick Joarder <[email protected]>
Reviewed-by: Oleksandr Andrushchenko <[email protected]>
---
drivers/gpu/drm/xen/xen_drm_front_gem.c | 18 +++++-------------
1 file changed, 5 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/xen/xen_drm_front_gem.c b/drivers/gpu/drm/xen/xen_drm_front_gem.c
index 28bc501..dd0602d 100644
--- a/drivers/gpu/drm/xen/xen_drm_front_gem.c
+++ b/drivers/gpu/drm/xen/xen_drm_front_gem.c
@@ -224,8 +224,7 @@ struct drm_gem_object *
static int gem_mmap_obj(struct xen_gem_object *xen_obj,
struct vm_area_struct *vma)
{
- unsigned long addr = vma->vm_start;
- int i;
+ int ret;

/*
* clear the VM_PFNMAP flag that was set by drm_gem_mmap(), and set the
@@ -246,18 +245,11 @@ static int gem_mmap_obj(struct xen_gem_object *xen_obj,
* FIXME: as we insert all the pages now then no .fault handler must
* be called, so don't provide one
*/
- for (i = 0; i < xen_obj->num_pages; i++) {
- int ret;
-
- ret = vm_insert_page(vma, addr, xen_obj->pages[i]);
- if (ret < 0) {
- DRM_ERROR("Failed to insert pages into vma: %d\n", ret);
- return ret;
- }
+ ret = vm_map_pages(vma, xen_obj->pages, xen_obj->num_pages);
+ if (ret < 0)
+ DRM_ERROR("Failed to map pages into vma: %d\n", ret);

- addr += PAGE_SIZE;
- }
- return 0;
+ return ret;
}

int xen_drm_front_gem_mmap(struct file *filp, struct vm_area_struct *vma)
--
1.9.1


2019-03-19 02:24:33

by Souptick Joarder

[permalink] [raw]
Subject: [RESEND PATCH v4 4/9] drm/rockchip/rockchip_drm_gem.c: Convert to use vm_map_pages()

Convert to use vm_map_pages() to map range of kernel
memory to user vma.

Tested on Rockchip hardware and display is working,
including talking to Lima via prime.

Signed-off-by: Souptick Joarder <[email protected]>
Tested-by: Heiko Stuebner <[email protected]>
---
drivers/gpu/drm/rockchip/rockchip_drm_gem.c | 17 ++---------------
1 file changed, 2 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
index a8db758..a2ebb08 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
@@ -221,26 +221,13 @@ static int rockchip_drm_gem_object_mmap_iommu(struct drm_gem_object *obj,
struct vm_area_struct *vma)
{
struct rockchip_gem_object *rk_obj = to_rockchip_obj(obj);
- unsigned int i, count = obj->size >> PAGE_SHIFT;
+ unsigned int count = obj->size >> PAGE_SHIFT;
unsigned long user_count = vma_pages(vma);
- unsigned long uaddr = vma->vm_start;
- unsigned long offset = vma->vm_pgoff;
- unsigned long end = user_count + offset;
- int ret;

if (user_count == 0)
return -ENXIO;
- if (end > count)
- return -ENXIO;

- for (i = offset; i < end; i++) {
- ret = vm_insert_page(vma, uaddr, rk_obj->pages[i]);
- if (ret)
- return ret;
- uaddr += PAGE_SIZE;
- }
-
- return 0;
+ return vm_map_pages(vma, rk_obj->pages, count);
}

static int rockchip_drm_gem_object_mmap_dma(struct drm_gem_object *obj,
--
1.9.1


2019-03-19 02:25:34

by Souptick Joarder

[permalink] [raw]
Subject: [RESEND PATCH v4 7/9] videobuf2/videobuf2-dma-sg.c: Convert to use vm_map_pages()

Convert to use vm_map_pages() to map range of kernel memory
to user vma.

vm_pgoff is treated in V4L2 API as a 'cookie' to select a buffer,
not as a in-buffer offset by design and it always want to mmap a
whole buffer from its beginning.

Signed-off-by: Souptick Joarder <[email protected]>
Suggested-by: Marek Szyprowski <[email protected]>
Reviewed-by: Marek Szyprowski <[email protected]>
---
drivers/media/common/videobuf2/videobuf2-core.c | 7 +++++++
.../media/common/videobuf2/videobuf2-dma-contig.c | 6 ------
drivers/media/common/videobuf2/videobuf2-dma-sg.c | 22 ++++++----------------
3 files changed, 13 insertions(+), 22 deletions(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
index 70e8c33..ca4577a 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -2175,6 +2175,13 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
goto unlock;
}

+ /*
+ * vm_pgoff is treated in V4L2 API as a 'cookie' to select a buffer,
+ * not as a in-buffer offset. We always want to mmap a whole buffer
+ * from its beginning.
+ */
+ vma->vm_pgoff = 0;
+
ret = call_memop(vb, mmap, vb->planes[plane].mem_priv, vma);

unlock:
diff --git a/drivers/media/common/videobuf2/videobuf2-dma-contig.c b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
index aff0ab7..46245c5 100644
--- a/drivers/media/common/videobuf2/videobuf2-dma-contig.c
+++ b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
@@ -186,12 +186,6 @@ static int vb2_dc_mmap(void *buf_priv, struct vm_area_struct *vma)
return -EINVAL;
}

- /*
- * dma_mmap_* uses vm_pgoff as in-buffer offset, but we want to
- * map whole buffer
- */
- vma->vm_pgoff = 0;
-
ret = dma_mmap_attrs(buf->dev, vma, buf->cookie,
buf->dma_addr, buf->size, buf->attrs);

diff --git a/drivers/media/common/videobuf2/videobuf2-dma-sg.c b/drivers/media/common/videobuf2/videobuf2-dma-sg.c
index 015e737..d6b8eca 100644
--- a/drivers/media/common/videobuf2/videobuf2-dma-sg.c
+++ b/drivers/media/common/videobuf2/videobuf2-dma-sg.c
@@ -328,28 +328,18 @@ static unsigned int vb2_dma_sg_num_users(void *buf_priv)
static int vb2_dma_sg_mmap(void *buf_priv, struct vm_area_struct *vma)
{
struct vb2_dma_sg_buf *buf = buf_priv;
- unsigned long uaddr = vma->vm_start;
- unsigned long usize = vma->vm_end - vma->vm_start;
- int i = 0;
+ int err;

if (!buf) {
printk(KERN_ERR "No memory to map\n");
return -EINVAL;
}

- do {
- int ret;
-
- ret = vm_insert_page(vma, uaddr, buf->pages[i++]);
- if (ret) {
- printk(KERN_ERR "Remapping memory, error: %d\n", ret);
- return ret;
- }
-
- uaddr += PAGE_SIZE;
- usize -= PAGE_SIZE;
- } while (usize > 0);
-
+ err = vm_map_pages(vma, buf->pages, buf->num_pages);
+ if (err) {
+ printk(KERN_ERR "Remapping memory, error: %d\n", err);
+ return err;
+ }

/*
* Use common vm_area operations to track buffer refcount.
--
1.9.1


2019-03-19 02:25:50

by Souptick Joarder

[permalink] [raw]
Subject: [RESEND PATCH v4 6/9] iommu/dma-iommu.c: Convert to use vm_map_pages()

Convert to use vm_map_pages() to map range of kernel
memory to user vma.

Signed-off-by: Souptick Joarder <[email protected]>
---
drivers/iommu/dma-iommu.c | 12 +-----------
1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index d19f3d6..bacebff 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -620,17 +620,7 @@ struct page **iommu_dma_alloc(struct device *dev, size_t size, gfp_t gfp,

int iommu_dma_mmap(struct page **pages, size_t size, struct vm_area_struct *vma)
{
- unsigned long uaddr = vma->vm_start;
- unsigned int i, count = PAGE_ALIGN(size) >> PAGE_SHIFT;
- int ret = -ENXIO;
-
- for (i = vma->vm_pgoff; i < count && uaddr < vma->vm_end; i++) {
- ret = vm_insert_page(vma, uaddr, pages[i]);
- if (ret)
- break;
- uaddr += PAGE_SIZE;
- }
- return ret;
+ return vm_map_pages(vma, pages, PAGE_ALIGN(size) >> PAGE_SHIFT);
}

static dma_addr_t __iommu_dma_map(struct device *dev, phys_addr_t phys,
--
1.9.1


2019-03-19 02:26:34

by Souptick Joarder

[permalink] [raw]
Subject: [RESEND PATCH v4 8/9] xen/gntdev.c: Convert to use vm_map_pages()

Convert to use vm_map_pages() to map range of kernel
memory to user vma.

map->count is passed to vm_map_pages() and internal API
verify map->count against count ( count = vma_pages(vma))
for page array boundary overrun condition.

Signed-off-by: Souptick Joarder <[email protected]>
Reviewed-by: Boris Ostrovsky <[email protected]>
---
drivers/xen/gntdev.c | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c
index 5efc5ee..5d64262 100644
--- a/drivers/xen/gntdev.c
+++ b/drivers/xen/gntdev.c
@@ -1084,7 +1084,7 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma)
int index = vma->vm_pgoff;
int count = vma_pages(vma);
struct gntdev_grant_map *map;
- int i, err = -EINVAL;
+ int err = -EINVAL;

if ((vma->vm_flags & VM_WRITE) && !(vma->vm_flags & VM_SHARED))
return -EINVAL;
@@ -1145,12 +1145,9 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma)
goto out_put_map;

if (!use_ptemod) {
- for (i = 0; i < count; i++) {
- err = vm_insert_page(vma, vma->vm_start + i*PAGE_SIZE,
- map->pages[i]);
- if (err)
- goto out_put_map;
- }
+ err = vm_map_pages(vma, map->pages, map->count);
+ if (err)
+ goto out_put_map;
} else {
#ifdef CONFIG_X86
/*
--
1.9.1


2019-03-19 02:29:03

by Souptick Joarder

[permalink] [raw]
Subject: [RESEND PATCH v4 9/9] xen/privcmd-buf.c: Convert to use vm_map_pages_zero()

Convert to use vm_map_pages_zero() to map range of kernel
memory to user vma.

This driver has ignored vm_pgoff. We could later "fix" these drivers
to behave according to the normal vm_pgoff offsetting simply by
removing the _zero suffix on the function name and if that causes
regressions, it gives us an easy way to revert.

Signed-off-by: Souptick Joarder <[email protected]>
Reviewed-by: Boris Ostrovsky <[email protected]>
---
drivers/xen/privcmd-buf.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/xen/privcmd-buf.c b/drivers/xen/privcmd-buf.c
index de01a6d..d02dc43 100644
--- a/drivers/xen/privcmd-buf.c
+++ b/drivers/xen/privcmd-buf.c
@@ -166,12 +166,8 @@ static int privcmd_buf_mmap(struct file *file, struct vm_area_struct *vma)
if (vma_priv->n_pages != count)
ret = -ENOMEM;
else
- for (i = 0; i < vma_priv->n_pages; i++) {
- ret = vm_insert_page(vma, vma->vm_start + i * PAGE_SIZE,
- vma_priv->pages[i]);
- if (ret)
- break;
- }
+ ret = vm_map_pages_zero(vma, vma_priv->pages,
+ vma_priv->n_pages);

if (ret)
privcmd_buf_vmapriv_free(vma_priv);
--
1.9.1


2019-04-01 05:27:10

by Souptick Joarder

[permalink] [raw]
Subject: Re: [RESEND PATCH v4 0/9] mm: Use vm_map_pages() and vm_map_pages_zero() API

Hi Andrew,

On Tue, Mar 19, 2019 at 7:47 AM Souptick Joarder <[email protected]> wrote:
>
> Previouly drivers have their own way of mapping range of
> kernel pages/memory into user vma and this was done by
> invoking vm_insert_page() within a loop.
>
> As this pattern is common across different drivers, it can
> be generalized by creating new functions and use it across
> the drivers.
>
> vm_map_pages() is the API which could be used to map
> kernel memory/pages in drivers which has considered vm_pgoff.
>
> vm_map_pages_zero() is the API which could be used to map
> range of kernel memory/pages in drivers which has not considered
> vm_pgoff. vm_pgoff is passed default as 0 for those drivers.
>
> We _could_ then at a later "fix" these drivers which are using
> vm_map_pages_zero() to behave according to the normal vm_pgoff
> offsetting simply by removing the _zero suffix on the function
> name and if that causes regressions, it gives us an easy way to revert.
>
> Tested on Rockchip hardware and display is working fine, including talking
> to Lima via prime.
>
> v1 -> v2:
> Few Reviewed-by.
>
> Updated the change log in [8/9]
>
> In [7/9], vm_pgoff is treated in V4L2 API as a 'cookie'
> to select a buffer, not as a in-buffer offset by design
> and it always want to mmap a whole buffer from its beginning.
> Added additional changes after discussing with Marek and
> vm_map_pages() could be used instead of vm_map_pages_zero().
>
> v2 -> v3:
> Corrected the documentation as per review comment.
>
> As suggested in v2, renaming the interfaces to -
> *vm_insert_range() -> vm_map_pages()* and
> *vm_insert_range_buggy() -> vm_map_pages_zero()*.
> As the interface is renamed, modified the code accordingly,
> updated the change logs and modified the subject lines to use the
> new interfaces. There is no other change apart from renaming and
> using the new interface.
>
> Patch[1/9] & [4/9], Tested on Rockchip hardware.
>
> v3 -> v4:
> Fixed build warnings on patch [8/9] reported by kbuild test robot.
>
> Souptick Joarder (9):
> mm: Introduce new vm_map_pages() and vm_map_pages_zero() API
> arm: mm: dma-mapping: Convert to use vm_map_pages()
> drivers/firewire/core-iso.c: Convert to use vm_map_pages_zero()
> drm/rockchip/rockchip_drm_gem.c: Convert to use vm_map_pages()
> drm/xen/xen_drm_front_gem.c: Convert to use vm_map_pages()
> iommu/dma-iommu.c: Convert to use vm_map_pages()
> videobuf2/videobuf2-dma-sg.c: Convert to use vm_map_pages()
> xen/gntdev.c: Convert to use vm_map_pages()
> xen/privcmd-buf.c: Convert to use vm_map_pages_zero()

Is it fine to take these patches into mm tree for regression ?

>
> arch/arm/mm/dma-mapping.c | 22 ++----
> drivers/firewire/core-iso.c | 15 +---
> drivers/gpu/drm/rockchip/rockchip_drm_gem.c | 17 +----
> drivers/gpu/drm/xen/xen_drm_front_gem.c | 18 ++---
> drivers/iommu/dma-iommu.c | 12 +---
> drivers/media/common/videobuf2/videobuf2-core.c | 7 ++
> .../media/common/videobuf2/videobuf2-dma-contig.c | 6 --
> drivers/media/common/videobuf2/videobuf2-dma-sg.c | 22 ++----
> drivers/xen/gntdev.c | 11 ++-
> drivers/xen/privcmd-buf.c | 8 +--
> include/linux/mm.h | 4 ++
> mm/memory.c | 81 ++++++++++++++++++++++
> mm/nommu.c | 14 ++++
> 13 files changed, 134 insertions(+), 103 deletions(-)
>
> --
> 1.9.1
>

2019-04-09 06:18:56

by Souptick Joarder

[permalink] [raw]
Subject: Re: [RESEND PATCH v4 0/9] mm: Use vm_map_pages() and vm_map_pages_zero() API

Hi Andrew/ Michal,

On Mon, Apr 1, 2019 at 10:56 AM Souptick Joarder <[email protected]> wrote:
>
> Hi Andrew,
>
> On Tue, Mar 19, 2019 at 7:47 AM Souptick Joarder <[email protected]> wrote:
> >
> > Previouly drivers have their own way of mapping range of
> > kernel pages/memory into user vma and this was done by
> > invoking vm_insert_page() within a loop.
> >
> > As this pattern is common across different drivers, it can
> > be generalized by creating new functions and use it across
> > the drivers.
> >
> > vm_map_pages() is the API which could be used to map
> > kernel memory/pages in drivers which has considered vm_pgoff.
> >
> > vm_map_pages_zero() is the API which could be used to map
> > range of kernel memory/pages in drivers which has not considered
> > vm_pgoff. vm_pgoff is passed default as 0 for those drivers.
> >
> > We _could_ then at a later "fix" these drivers which are using
> > vm_map_pages_zero() to behave according to the normal vm_pgoff
> > offsetting simply by removing the _zero suffix on the function
> > name and if that causes regressions, it gives us an easy way to revert.
> >
> > Tested on Rockchip hardware and display is working fine, including talking
> > to Lima via prime.
> >
> > v1 -> v2:
> > Few Reviewed-by.
> >
> > Updated the change log in [8/9]
> >
> > In [7/9], vm_pgoff is treated in V4L2 API as a 'cookie'
> > to select a buffer, not as a in-buffer offset by design
> > and it always want to mmap a whole buffer from its beginning.
> > Added additional changes after discussing with Marek and
> > vm_map_pages() could be used instead of vm_map_pages_zero().
> >
> > v2 -> v3:
> > Corrected the documentation as per review comment.
> >
> > As suggested in v2, renaming the interfaces to -
> > *vm_insert_range() -> vm_map_pages()* and
> > *vm_insert_range_buggy() -> vm_map_pages_zero()*.
> > As the interface is renamed, modified the code accordingly,
> > updated the change logs and modified the subject lines to use the
> > new interfaces. There is no other change apart from renaming and
> > using the new interface.
> >
> > Patch[1/9] & [4/9], Tested on Rockchip hardware.
> >
> > v3 -> v4:
> > Fixed build warnings on patch [8/9] reported by kbuild test robot.
> >
> > Souptick Joarder (9):
> > mm: Introduce new vm_map_pages() and vm_map_pages_zero() API
> > arm: mm: dma-mapping: Convert to use vm_map_pages()
> > drivers/firewire/core-iso.c: Convert to use vm_map_pages_zero()
> > drm/rockchip/rockchip_drm_gem.c: Convert to use vm_map_pages()
> > drm/xen/xen_drm_front_gem.c: Convert to use vm_map_pages()
> > iommu/dma-iommu.c: Convert to use vm_map_pages()
> > videobuf2/videobuf2-dma-sg.c: Convert to use vm_map_pages()
> > xen/gntdev.c: Convert to use vm_map_pages()
> > xen/privcmd-buf.c: Convert to use vm_map_pages_zero()
>
> Is it fine to take these patches into mm tree for regression ?

v4 of this series has not received any further comments/ kbuild error
in last 8 weeks (including
the previously posted v4).

Any suggestion, if it safe to take these changes through mm tree ? or any
other tree is preferred ?

>
> >
> > arch/arm/mm/dma-mapping.c | 22 ++----
> > drivers/firewire/core-iso.c | 15 +---
> > drivers/gpu/drm/rockchip/rockchip_drm_gem.c | 17 +----
> > drivers/gpu/drm/xen/xen_drm_front_gem.c | 18 ++---
> > drivers/iommu/dma-iommu.c | 12 +---
> > drivers/media/common/videobuf2/videobuf2-core.c | 7 ++
> > .../media/common/videobuf2/videobuf2-dma-contig.c | 6 --
> > drivers/media/common/videobuf2/videobuf2-dma-sg.c | 22 ++----
> > drivers/xen/gntdev.c | 11 ++-
> > drivers/xen/privcmd-buf.c | 8 +--
> > include/linux/mm.h | 4 ++
> > mm/memory.c | 81 ++++++++++++++++++++++
> > mm/nommu.c | 14 ++++
> > 13 files changed, 134 insertions(+), 103 deletions(-)
> >
> > --
> > 1.9.1
> >