diff mbox series

[v2,3/8] x86/mm: Remove "static" from vmap_pages_range()

Message ID 20231121212016.1154303-4-mhklinux@outlook.com (mailing list archive)
State New
Headers show
Series x86/coco: Mark CoCo VM pages not present when changing encrypted state | expand

Commit Message

Michael Kelley Nov. 21, 2023, 9:20 p.m. UTC
From: Michael Kelley <mhklinux@outlook.com>

The mm subsystem currently provides no mechanism to map memory pages
to a specified virtual address range.  A virtual address range can be
allocated using get_vm_area(), but the only function available for
mapping memory pages to a caller-specified address in that range is
ioremap_page_range(), which is inappropriate for system memory.

Fix this by allowing vmap_pages_range() to be used by callers outside
of vmalloc.c.

Signed-off-by: Michael Kelley <mhklinux@outlook.com>
---
 include/linux/vmalloc.h | 2 ++
 mm/vmalloc.c            | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

Comments

Christoph Hellwig Nov. 22, 2023, 6:26 a.m. UTC | #1
On Tue, Nov 21, 2023 at 01:20:11PM -0800, mhkelley58@gmail.com wrote:
> From: Michael Kelley <mhklinux@outlook.com>
> 
> The mm subsystem currently provides no mechanism to map memory pages
> to a specified virtual address range.  A virtual address range can be
> allocated using get_vm_area(), but the only function available for
> mapping memory pages to a caller-specified address in that range is
> ioremap_page_range(), which is inappropriate for system memory.
> 
> Fix this by allowing vmap_pages_range() to be used by callers outside
> of vmalloc.c.

I really do not want to expose vmap_pages_range.  Please try to come up
with a good way to encapsulate your map at a certain address primitive
and implement it in vmalloc.c.
Michael Kelley Nov. 23, 2023, 12:24 a.m. UTC | #2
From: Christoph Hellwig <hch@infradead.org> Sent: Tuesday, November 21, 2023 10:26 PM
> 
> On Tue, Nov 21, 2023 at 01:20:11PM -0800, mhkelley58@gmail.com wrote:
> > From: Michael Kelley <mhklinux@outlook.com>
> >
> > The mm subsystem currently provides no mechanism to map memory pages
> > to a specified virtual address range.  A virtual address range can be
> > allocated using get_vm_area(), but the only function available for
> > mapping memory pages to a caller-specified address in that range is
> > ioremap_page_range(), which is inappropriate for system memory.
> >
> > Fix this by allowing vmap_pages_range() to be used by callers outside
> > of vmalloc.c.
> 
> I really do not want to expose vmap_pages_range.  Please try to come up
> with a good way to encapsulate your map at a certain address primitive
> and implement it in vmalloc.c.

To clarify, is your concern narrowly about vmap_pages_range()
specifically?  Or is your concern more generally about having two separate
steps as applied to system memory:  1) allocate the virtual address
space and 2) do the mapping?  The two separate steps are already
available for MMIO space.  Doing the equivalent for system memory
should be straightforward.

Conversely, combining the two steps into a single new vmap() variant
would be a little messy, but can probably be made to work.  This
combined approach will be less efficient since my use case does a single
allocation of virtual address space and repeatedly maps/unmaps the
same page in that space.  I would need to take some measurements
to see if the inefficiency actually matters.

Michael
Christoph Hellwig Nov. 23, 2023, 7:32 a.m. UTC | #3
On Thu, Nov 23, 2023 at 12:24:49AM +0000, Michael Kelley wrote:
> > I really do not want to expose vmap_pages_range.  Please try to come up
> > with a good way to encapsulate your map at a certain address primitive
> > and implement it in vmalloc.c.
> 
> To clarify, is your concern narrowly about vmap_pages_range()
> specifically?

The prime concern is that it took a lot of effort to make
vmap_pages_range static and remove all the abuses.  I absolutely
object to undoing that.
Michael Kelley Nov. 27, 2023, 1:06 a.m. UTC | #4
From: Christoph Hellwig <hch@infradead.org> Sent: Wednesday, November 22, 2023 11:32 PM
> 
> On Thu, Nov 23, 2023 at 12:24:49AM +0000, Michael Kelley wrote:
> > > I really do not want to expose vmap_pages_range.  Please try to come up
> > > with a good way to encapsulate your map at a certain address primitive
> > > and implement it in vmalloc.c.
> >
> > To clarify, is your concern narrowly about vmap_pages_range()
> > specifically?
> 
> The prime concern is that it took a lot of effort to make
> vmap_pages_range static and remove all the abuses.  I absolutely
> object to undoing that.

OK, so I assume that means a new variant of vmap_pages_range(),
such as one that always sets the page_shift parameter to PAGE_SIZE,
is also disallowed because of the same potential for abuse.

So the only way to map a system memory page to a vmalloc
vaddr is via vmap() or some vmap() variant, which always
creates a new vmalloc area via get_vm_area().  I've done the
perf measurements, and that approach won't work for this use
case.  Independent of the alignment requirements, the churn in
creating and removing a lot of vmalloc areas has too much perf
impact.   The use case needs to create a single vmalloc area, and
then repeatedly map/unmap a page in that existing area.

I'll have to handle the top-level problem in this patch set in
a completely different way.

Michael
diff mbox series

Patch

diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
index c720be70c8dd..ee12f5226a45 100644
--- a/include/linux/vmalloc.h
+++ b/include/linux/vmalloc.h
@@ -233,6 +233,8 @@  static inline bool is_vm_area_hugepages(const void *addr)
 
 #ifdef CONFIG_MMU
 void vunmap_range(unsigned long addr, unsigned long end);
+int vmap_pages_range(unsigned long addr, unsigned long end, pgprot_t prot,
+			struct page **pages, unsigned int page_shift);
 static inline void set_vm_flush_reset_perms(void *addr)
 {
 	struct vm_struct *vm = find_vm_area(addr);
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index d12a17fc0c17..b2a72bd317c6 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -625,7 +625,7 @@  int vmap_pages_range_noflush(unsigned long addr, unsigned long end,
  * RETURNS:
  * 0 on success, -errno on failure.
  */
-static int vmap_pages_range(unsigned long addr, unsigned long end,
+int vmap_pages_range(unsigned long addr, unsigned long end,
 		pgprot_t prot, struct page **pages, unsigned int page_shift)
 {
 	int err;