diff options
author | Konstantin Belousov <kib@FreeBSD.org> | 2019-05-16 13:28:48 +0000 |
---|---|---|
committer | Konstantin Belousov <kib@FreeBSD.org> | 2019-05-16 13:28:48 +0000 |
commit | 4d3b28bcdcc494059c30887ad1721c8eb6c5eada (patch) | |
tree | db3a21ac2f601c06c225e3a9439a5aa7374a4613 /sys/amd64/include | |
parent | a9fd669b4a564e3dc4668dd5a8bfe341cbbefaa9 (diff) | |
download | src-4d3b28bcdcc494059c30887ad1721c8eb6c5eada.tar.gz src-4d3b28bcdcc494059c30887ad1721c8eb6c5eada.zip |
amd64 pmap: rework delayed invalidation, removing global mutex.
For machines having cmpxcgh16b instruction, i.e. everything but very
early Athlons, provide lockless implementation of delayed
invalidation.
The implementation maintains lock-less single-linked list with the
trick from the T.L. Harris article about volatile mark of the elements
being removed. Double-CAS is used to atomically update both link and
generation. New thread starting DI appends itself to the end of the
queue, setting the generation to the generation of the last element
+1. On DI finish, thread donates its generation to the previous
element. The generation of the fake head of the list is the last
passed DI generation. Basically, the implementation is a queued
spinlock but without spinlock.
Many thanks both to Peter Holm and Mark Johnson for keeping with me
while I produced intermediate versions of the patch.
Reviewed by: markj
Tested by: pho
Sponsored by: The FreeBSD Foundation
MFC after: 1 month
MFC note: td_md.md_invl_gen should go to the end of struct thread
Differential revision: https://reviews.freebsd.org/D19630
Notes
Notes:
svn path=/head/; revision=347695
Diffstat (limited to 'sys/amd64/include')
-rw-r--r-- | sys/amd64/include/pmap.h | 2 | ||||
-rw-r--r-- | sys/amd64/include/proc.h | 11 |
2 files changed, 11 insertions, 2 deletions
diff --git a/sys/amd64/include/pmap.h b/sys/amd64/include/pmap.h index 91d6fb2f934b..d6739c2cea4e 100644 --- a/sys/amd64/include/pmap.h +++ b/sys/amd64/include/pmap.h @@ -441,6 +441,7 @@ void *pmap_mapbios(vm_paddr_t, vm_size_t); void *pmap_mapdev(vm_paddr_t, vm_size_t); void *pmap_mapdev_attr(vm_paddr_t, vm_size_t, int); void *pmap_mapdev_pciecfg(vm_paddr_t pa, vm_size_t size); +bool pmap_not_in_di(void); boolean_t pmap_page_is_mapped(vm_page_t m); void pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma); void pmap_pinit_pml4(vm_page_t); @@ -465,6 +466,7 @@ void pmap_pti_pcid_invlrng(uint64_t ucr3, uint64_t kcr3, vm_offset_t sva, int pmap_pkru_clear(pmap_t pmap, vm_offset_t sva, vm_offset_t eva); int pmap_pkru_set(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, u_int keyidx, int flags); +void pmap_thread_init_invl_gen(struct thread *td); int pmap_vmspace_copy(pmap_t dst_pmap, pmap_t src_pmap); #endif /* _KERNEL */ diff --git a/sys/amd64/include/proc.h b/sys/amd64/include/proc.h index c063849972fc..21d6cce7954f 100644 --- a/sys/amd64/include/proc.h +++ b/sys/amd64/include/proc.h @@ -50,10 +50,17 @@ struct proc_ldt { int ldt_refcnt; }; +#define PMAP_INVL_GEN_NEXT_INVALID 0x1ULL struct pmap_invl_gen { u_long gen; /* (k) */ - LIST_ENTRY(pmap_invl_gen) link; /* (pp) */ -}; + union { + LIST_ENTRY(pmap_invl_gen) link; /* (pp) */ + struct { + struct pmap_invl_gen *next; + u_char saved_pri; + }; + }; +} __aligned(16); /* * Machine-dependent part of the proc structure for AMD64. |