Disable global mappings when using PCID.
authorpatrick <patrick@openbsd.org>
Wed, 19 May 2021 17:46:36 +0000 (17:46 +0000)
committerpatrick <patrick@openbsd.org>
Wed, 19 May 2021 17:46:36 +0000 (17:46 +0000)
commitb1d72b5f52b57d4b462f4d9242bd78d6b7a9edd2
tree872dcaaaa96d6ebd392f913bf4cdd5d698407a9c
parent1378d87c3259676b08343c99b25fa39baec92be3
Disable global mappings when using PCID.

Page table mappings are frequently created and destroyed in the kernel
address space.  Traditionally, these mappings have been marked as
"global" mappings which means that a TLB flush via %cr3 load does not
invalidate them.  This is ok as these mappings are the same for all
processes.

With the advent of MELTDOWN, global mappings were disabled for CPUs
that are affected by rogue data cache load (RDCL aka MELTDOWN).  To
compensate for this we started using PCID and the kernel got its own
process context identifier.  Thus the hardware is allowed to cache
kernel mappings again.

However, a CPU that supports PCID but is _not_ affected by MELTDOWN
(i.e. ARCH_CAPABILTIES.RDCL_NO=1) will now use both: global PTE
mappings and PCID.

This is a problem if range based TLB invalidations are used to update/
flush cached TLBs after a change to the kernel page tables.  The reason
is that the invpcid instruction (function 0) that is used to remove the
cached TLBs will not remove global mappings.  In the non-PCID case invlpg
is used instead which does remove global mappings.  In the MELTDOWN case,
global mappings are not used at all.

The solution is to not use global mappings if PCID is active, as the
latter should already by enough to let the hardware cache kernel address
translations across address space switches and the global flag is not
required.

From Christian Ehrhardt
ok bluhm@ guenther@ mlarkin@
sys/arch/amd64/amd64/pmap.c