]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/commit
riscv: Fix a race in pmap_pinit()
authorMark Johnston <markj@FreeBSD.org>
Tue, 8 Feb 2022 18:15:54 +0000 (13:15 -0500)
committerMark Johnston <markj@FreeBSD.org>
Tue, 8 Feb 2022 18:31:55 +0000 (13:31 -0500)
commitc862d5f2a789925efe70fc64247caa5148e98a54
tree682dba0914df779fc7b5ce150b651fe8a22daa05
parent5de79eeddb9de079d108d1312148bcbefce45c27
riscv: Fix a race in pmap_pinit()

All pmaps share the top half of the address space.  With 3-level page
tables, the top-level kernel map entries are not static: they might
change if the kernel map is extended (via pmap_growkernel()) or a 1GB
mapping in the direct map is demoted (not implemented yet).  Thus the
riscv pmap maintains the allpmaps list to synchronize updates to
top-level entries.

When a pmap is created, it is inserted into this list after copying
top-level entries from the kernel pmap.  The copying is done without
holding the allpmaps lock, and it is possible for pmap_pinit() to race
with kernel map updates.  In particular, if a thread is modifying L1
entries, and a concurrent pmap_pinit() copies the old version of the
entries, it might not receive the update.

Fix the problem by copying the kernel map entries after inserting the
pmap into the list.  This ensures that the nascent pmap always receives
updates, though pmap_distribute_l1() may race with the page copy.

Reviewed by: mhorne, jhb
MFC after: 2 weeks
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D34158
sys/riscv/riscv/pmap.c