mirror of
https://git.FreeBSD.org/src.git
synced 2024-11-28 08:02:54 +00:00
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
This commit is contained in:
parent
485f783f88
commit
1e0e335b0f
@ -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 @@ pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
|
||||
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:
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user