git: 4a235049082e - main - riscv: Fix pmap_kextract racing with concurrent superpage promotion/demotion
Jessica Clarke
jrtc27 at FreeBSD.org
Thu Jul 22 19:04:23 UTC 2021
The branch main has been updated by jrtc27:
URL: https://cgit.FreeBSD.org/src/commit/?id=4a235049082ee1cb044873ad9aff12cf73d0fd3b
commit 4a235049082ee1cb044873ad9aff12cf73d0fd3b
Author: Jessica Clarke <jrtc27 at FreeBSD.org>
AuthorDate: 2021-07-22 19:02:14 +0000
Commit: Jessica Clarke <jrtc27 at FreeBSD.org>
CommitDate: 2021-07-22 19:02:14 +0000
riscv: Fix pmap_kextract racing with concurrent superpage promotion/demotion
This repeats amd64's cfcbf8c6fd3b (r180498) and i386's cf3508519c5e
(r202894) but for riscv; pmap_kextract must be lock-free and so it can
race with superpage promotion and demotion, thus the L2 entry must only
be loaded once to avoid using inconsistent state.
PR: 250866
Reviewed by: markj, mhorne
Tested by: David Gilbert <dgilbert at daveg.ca>
MFC after: 1 week
Differential Revision: https://reviews.freebsd.org/D31253
---
sys/riscv/riscv/pmap.c | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/sys/riscv/riscv/pmap.c b/sys/riscv/riscv/pmap.c
index 39595b10d7b2..0bb22bd13bbe 100644
--- a/sys/riscv/riscv/pmap.c
+++ b/sys/riscv/riscv/pmap.c
@@ -872,7 +872,7 @@ pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot)
vm_paddr_t
pmap_kextract(vm_offset_t va)
{
- pd_entry_t *l2;
+ pd_entry_t *l2, l2e;
pt_entry_t *l3;
vm_paddr_t pa;
@@ -882,14 +882,23 @@ pmap_kextract(vm_offset_t va)
l2 = pmap_l2(kernel_pmap, va);
if (l2 == NULL)
panic("pmap_kextract: No l2");
- if ((pmap_load(l2) & PTE_RX) != 0) {
+ l2e = pmap_load(l2);
+ /*
+ * Beware of concurrent promotion and demotion! We must
+ * use l2e rather than loading from l2 multiple times to
+ * ensure we see a consistent state, including the
+ * implicit load in pmap_l2_to_l3. It is, however, safe
+ * to use an old l2e because the L3 page is preserved by
+ * promotion.
+ */
+ if ((l2e & PTE_RX) != 0) {
/* superpages */
- pa = L2PTE_TO_PHYS(pmap_load(l2));
+ pa = L2PTE_TO_PHYS(l2e);
pa |= (va & L2_OFFSET);
return (pa);
}
- l3 = pmap_l2_to_l3(l2, va);
+ l3 = pmap_l2_to_l3(&l2e, va);
if (l3 == NULL)
panic("pmap_kextract: No l3...");
pa = PTE_TO_PHYS(pmap_load(l3));
More information about the dev-commits-src-all
mailing list