Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 14 Apr 2023 23:54:09 GMT
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 1e0e335b0f0d - main - amd64: fix PKRU and swapout interaction
Message-ID:  <202304142354.33ENs9MH062220@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=1e0e335b0f0dbae8ce49307377b23ef3673bd402

commit 1e0e335b0f0dbae8ce49307377b23ef3673bd402
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2023-04-13 11:37:35 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2023-04-14 23:53:59 +0000

    amd64: fix PKRU and swapout interaction
    
    When vm_map_remove() is called from vm_swapout_map_deactivate_pages()
    due to swapout, PKRU attributes for the removed range must be kept
    intact.  Provide a variant of pmap_remove(), pmap_map_delete(), to
    allow pmap to distinguish between real removes of the UVA mappings
    and any other internal removes, e.g. swapout.
    
    For non-amd64, pmap_map_delete() is stubbed by define to pmap_remove().
    
    Reported by:    andrew
    Reviewed by:    markj
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D39556
---
 sys/amd64/amd64/pmap.c     | 37 ++++++++++++++++++++++++++++---------
 sys/amd64/include/pmap.h   |  1 +
 sys/arm/include/pmap.h     |  1 +
 sys/arm64/include/pmap.h   |  1 +
 sys/i386/include/pmap.h    |  1 +
 sys/powerpc/include/pmap.h |  1 +
 sys/riscv/include/pmap.h   |  1 +
 sys/vm/vm_map.c            |  2 +-
 8 files changed, 35 insertions(+), 10 deletions(-)

diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
index a31cdb2a8215..e8a88aab3225 100644
--- a/sys/amd64/amd64/pmap.c
+++ b/sys/amd64/amd64/pmap.c
@@ -6280,14 +6280,8 @@ pmap_remove_ptes(pmap_t pmap, vm_offset_t sva, vm_offset_t eva,
 	return (anyvalid);
 }
 
-/*
- *	Remove the given range of addresses from the specified map.
- *
- *	It is assumed that the start and end are properly
- *	rounded to the page size.
- */
-void
-pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
+static void
+pmap_remove1(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, bool map_delete)
 {
 	struct rwlock *lock;
 	vm_page_t mt;
@@ -6319,7 +6313,8 @@ pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
 
 	pmap_delayed_invl_start();
 	PMAP_LOCK(pmap);
-	pmap_pkru_on_remove(pmap, sva, eva);
+	if (map_delete)
+		pmap_pkru_on_remove(pmap, sva, eva);
 
 	/*
 	 * special handling of removing one page.  a very
@@ -6441,6 +6436,30 @@ out:
 	vm_page_free_pages_toq(&free, true);
 }
 
+/*
+ *	Remove the given range of addresses from the specified map.
+ *
+ *	It is assumed that the start and end are properly
+ *	rounded to the page size.
+ */
+void
+pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
+{
+	pmap_remove1(pmap, sva, eva, false);
+}
+
+/*
+ *	Remove the given range of addresses as part of a logical unmap
+ *	operation. This has the effect of calling pmap_remove(), but
+ *	also clears any metadata that should persist for the lifetime
+ *	of a logical mapping.
+ */
+void
+pmap_map_delete(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
+{
+	pmap_remove1(pmap, sva, eva, true);
+}
+
 /*
  *	Routine:	pmap_remove_all
  *	Function:
diff --git a/sys/amd64/include/pmap.h b/sys/amd64/include/pmap.h
index a7e456d80fcf..d74f25cc8024 100644
--- a/sys/amd64/include/pmap.h
+++ b/sys/amd64/include/pmap.h
@@ -486,6 +486,7 @@ void	pmap_force_invalidate_cache_range(vm_offset_t sva, vm_offset_t eva);
 void	pmap_get_mapping(pmap_t pmap, vm_offset_t va, uint64_t *ptr, int *num);
 boolean_t pmap_map_io_transient(vm_page_t *, vm_offset_t *, int, boolean_t);
 void	pmap_unmap_io_transient(vm_page_t *, vm_offset_t *, int, boolean_t);
+void	pmap_map_delete(pmap_t, vm_offset_t, vm_offset_t);
 void	pmap_pti_add_kva(vm_offset_t sva, vm_offset_t eva, bool exec);
 void	pmap_pti_remove_kva(vm_offset_t sva, vm_offset_t eva);
 void	pmap_pti_pcid_invalidate(uint64_t ucr3, uint64_t kcr3);
diff --git a/sys/arm/include/pmap.h b/sys/arm/include/pmap.h
index b16651f789cc..977a1e989b42 100644
--- a/sys/arm/include/pmap.h
+++ b/sys/arm/include/pmap.h
@@ -45,6 +45,7 @@ extern vm_offset_t virtual_end;
 void *pmap_kenter_temporary(vm_paddr_t, int);
 #define	pmap_page_is_write_mapped(m)	(((m)->a.flags & PGA_WRITEABLE) != 0)
 void pmap_page_set_memattr(vm_page_t, vm_memattr_t);
+#define	pmap_map_delete(pmap, sva, eva)	pmap_remove(pmap, sva, eva)
 
 void *pmap_mapdev(vm_paddr_t, vm_size_t);
 void pmap_unmapdev(void *, vm_size_t);
diff --git a/sys/arm64/include/pmap.h b/sys/arm64/include/pmap.h
index 2847fa8dd439..8e3e81f2a5d3 100644
--- a/sys/arm64/include/pmap.h
+++ b/sys/arm64/include/pmap.h
@@ -154,6 +154,7 @@ int	pmap_pinit_stage(pmap_t, enum pmap_stage, int);
 bool	pmap_ps_enabled(pmap_t pmap);
 uint64_t pmap_to_ttbr0(pmap_t pmap);
 void	pmap_disable_promotion(vm_offset_t sva, vm_size_t size);
+#define	pmap_map_delete(pmap, sva, eva)	pmap_remove(pmap, sva, eva)
 
 void	*pmap_mapdev(vm_paddr_t, vm_size_t);
 void	*pmap_mapbios(vm_paddr_t, vm_size_t);
diff --git a/sys/i386/include/pmap.h b/sys/i386/include/pmap.h
index 1ee13871bc32..87570929e0dd 100644
--- a/sys/i386/include/pmap.h
+++ b/sys/i386/include/pmap.h
@@ -258,6 +258,7 @@ void	pmap_invalidate_cache_range(vm_offset_t sva, vm_offset_t eva);
 void	pmap_force_invalidate_cache_range(vm_offset_t sva, vm_offset_t eva);
 void	*pmap_trm_alloc(size_t size, int flags);
 void	pmap_trm_free(void *addr, size_t size);
+#define	pmap_map_delete(pmap, sva, eva)	pmap_remove(pmap, sva, eva)
 
 void	invltlb_glob(void);
 
diff --git a/sys/powerpc/include/pmap.h b/sys/powerpc/include/pmap.h
index 5746378c64ee..4ee9b6a67ef6 100644
--- a/sys/powerpc/include/pmap.h
+++ b/sys/powerpc/include/pmap.h
@@ -326,6 +326,7 @@ const char	*pmap_mmu_name(void);
 bool		pmap_ps_enabled(pmap_t pmap);
 int		pmap_nofault(pmap_t pmap, vm_offset_t va, vm_prot_t flags);
 boolean_t	pmap_page_is_mapped(vm_page_t m);
+#define	pmap_map_delete(pmap, sva, eva)	pmap_remove(pmap, sva, eva)
 
 void		pmap_page_array_startup(long count);
 
diff --git a/sys/riscv/include/pmap.h b/sys/riscv/include/pmap.h
index 04808422c2c2..88579e6448b5 100644
--- a/sys/riscv/include/pmap.h
+++ b/sys/riscv/include/pmap.h
@@ -57,6 +57,7 @@
 #define	pmap_page_get_memattr(m)	((m)->md.pv_memattr)
 #define	pmap_page_is_write_mapped(m)	(((m)->a.flags & PGA_WRITEABLE) != 0)
 void pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma);
+#define	pmap_map_delete(pmap, sva, eva)	pmap_remove(pmap, sva, eva)
 
 /*
  * Pmap stuff
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
index a7efa00da1e2..f5863a9b9939 100644
--- a/sys/vm/vm_map.c
+++ b/sys/vm/vm_map.c
@@ -3964,7 +3964,7 @@ vm_map_delete(vm_map_t map, vm_offset_t start, vm_offset_t end)
 		 */
 		if ((entry->eflags & MAP_ENTRY_IS_SUB_MAP) != 0 ||
 		    entry->object.vm_object != NULL)
-			pmap_remove(map->pmap, entry->start, entry->end);
+			pmap_map_delete(map->pmap, entry->start, entry->end);
 
 		if (entry->end == map->anon_loc)
 			map->anon_loc = entry->start;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202304142354.33ENs9MH062220>